From 01ff1a781e4fb6e9e106d3837981757521015c50 Mon Sep 17 00:00:00 2001
From: Benedikt Meurer <benny@xfce.org>
Date: Wed, 15 Mar 2006 02:47:44 +0000
Subject: [PATCH] 2006-03-15	Benedikt Meurer <benny@xfce.org>

	* acinclude.m4(BM_THUNAR_VFS_VOLUME_IMPL): Handle "none" properly.
	* thunar-vfs/thunar-vfs-volume-manager.c, thunar-vfs/Makefile.am,
	  thunar-vfs/thunar-vfs-volume-private.h, thunar-vfs/thunar-vfs.symbols,
	  thunar-vfs/thunar-vfs-volume.c, thunar-vfs/thunar-vfs-volume-none.c,
	  thunar-vfs/thunar-vfs-volume.h, thunar-vfs/thunar-vfs-volume-hal.c,
	  thunar-vfs/thunar-vfs-volume-freebsd.c: Improve the volume manager
	  implemenation. The ThunarVfsVolumeManager and ThunarVfsVolume inter-
	  faces are now abstract base classes, with the implementation API
	  completely separated from the public API. The HAL backend was fixed
	  to work around a strange HAL bug, where 'volume.is_mounted' is FALSE
	  for mounted volumes (instead of trusting HAL, we ask the kernel to
	  make sure we always display the proper state). Also, new signals
	  "mounted", "pre-unmount" and "unmounted" were added to both
	  ThunarVfsVolume and ThunarVfsVolumeManager, to allow applications to
	  perform certain actions for these events.
	* docs/reference/thunar-vfs/: Update the API documentation.
	* thunar/thunar-window.c: Whenever the user requests to unmount a
	  volume, check if the window displays a folder on this volume and if
	  so, go to the home folder, to make sure we don't display a probably
	  no longer existing mount point afterwards.




(Old svn revision: 20438)
---
 ChangeLog                                     |  23 +
 acinclude.m4                                  |   2 +
 .../thunar-vfs/thunar-vfs-sections.txt        |  15 +-
 .../tmpl/thunar-vfs-volume-manager.sgml       |  49 +-
 .../thunar-vfs/tmpl/thunar-vfs-volume.sgml    |  43 +-
 thunar-vfs/Makefile.am                        |   2 +
 thunar-vfs/thunar-vfs-volume-freebsd.c        | 171 +++---
 thunar-vfs/thunar-vfs-volume-hal.c            | 310 ++++++-----
 thunar-vfs/thunar-vfs-volume-manager.c        | 488 ++++++++++++++++++
 thunar-vfs/thunar-vfs-volume-none.c           |  83 ++-
 thunar-vfs/thunar-vfs-volume-private.h        | 111 ++++
 thunar-vfs/thunar-vfs-volume.c                | 397 ++++----------
 thunar-vfs/thunar-vfs-volume.h                |  99 +---
 thunar-vfs/thunar-vfs.symbols                 |   3 +
 thunar/thunar-window.c                        | 227 ++++----
 15 files changed, 1210 insertions(+), 813 deletions(-)
 create mode 100644 thunar-vfs/thunar-vfs-volume-manager.c
 create mode 100644 thunar-vfs/thunar-vfs-volume-private.h

diff --git a/ChangeLog b/ChangeLog
index 2bcb3c775..41d0f83a3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,26 @@
+2006-03-15	Benedikt Meurer <benny@xfce.org>
+
+	* acinclude.m4(BM_THUNAR_VFS_VOLUME_IMPL): Handle "none" properly.
+	* thunar-vfs/thunar-vfs-volume-manager.c, thunar-vfs/Makefile.am,
+	  thunar-vfs/thunar-vfs-volume-private.h, thunar-vfs/thunar-vfs.symbols,
+	  thunar-vfs/thunar-vfs-volume.c, thunar-vfs/thunar-vfs-volume-none.c,
+	  thunar-vfs/thunar-vfs-volume.h, thunar-vfs/thunar-vfs-volume-hal.c,
+	  thunar-vfs/thunar-vfs-volume-freebsd.c: Improve the volume manager
+	  implemenation. The ThunarVfsVolumeManager and ThunarVfsVolume inter-
+	  faces are now abstract base classes, with the implementation API
+	  completely separated from the public API. The HAL backend was fixed
+	  to work around a strange HAL bug, where 'volume.is_mounted' is FALSE
+	  for mounted volumes (instead of trusting HAL, we ask the kernel to
+	  make sure we always display the proper state). Also, new signals
+	  "mounted", "pre-unmount" and "unmounted" were added to both
+	  ThunarVfsVolume and ThunarVfsVolumeManager, to allow applications to
+	  perform certain actions for these events.
+	* docs/reference/thunar-vfs/: Update the API documentation.
+	* thunar/thunar-window.c: Whenever the user requests to unmount a
+	  volume, check if the window displays a folder on this volume and if
+	  so, go to the home folder, to make sure we don't display a probably
+	  no longer existing mount point afterwards.
+
 2006-03-14	Benedikt Meurer <benny@xfce.org>
 
 	* thunar-vfs/thunar-vfs-exec.{c,h}: Add thunar_vfs_exec_sync() helper
diff --git a/acinclude.m4 b/acinclude.m4
index 8e3e4de75..a0e1eba2d 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -79,6 +79,8 @@ AC_HELP_STRING([--with-volume-manager=@<:@auto/freebsd/hal/none@:>@], [The volum
     ac_bm_thunar_vfs_volume_impl=freebsd
   elif test x"$with_volume_manager" = x"hal"; then
     ac_bm_thunar_vfs_volume_impl=hal
+  elif test x"$with_volume_manager" = x"none"; then
+    ac_bm_thunar_vfs_volume_impl=none
   else
     dnl # Check target platform (auto-detection)
     case "$target_os" in
diff --git a/docs/reference/thunar-vfs/thunar-vfs-sections.txt b/docs/reference/thunar-vfs/thunar-vfs-sections.txt
index 8cad2a9f6..da13c59b9 100644
--- a/docs/reference/thunar-vfs/thunar-vfs-sections.txt
+++ b/docs/reference/thunar-vfs/thunar-vfs-sections.txt
@@ -386,7 +386,6 @@ thunar_vfs_humanize_size
 <TITLE>ThunarVfsVolume</TITLE>
 ThunarVfsVolumeKind
 ThunarVfsVolumeStatus
-ThunarVfsVolumeIface
 ThunarVfsVolume
 thunar_vfs_volume_get_kind
 thunar_vfs_volume_get_name
@@ -400,14 +399,16 @@ thunar_vfs_volume_lookup_icon_name
 thunar_vfs_volume_eject
 thunar_vfs_volume_mount
 thunar_vfs_volume_unmount
-thunar_vfs_volume_changed
 <SUBSECTION Standard>
+ThunarVfsVolumeClass
 THUNAR_VFS_TYPE_VFS_VOLUME_KIND
 THUNAR_VFS_TYPE_VFS_VOLUME_STATUS
 THUNAR_VFS_TYPE_VOLUME
 THUNAR_VFS_VOLUME
+THUNAR_VFS_VOLUME_CLASS
 THUNAR_VFS_IS_VOLUME
-THUNAR_VFS_VOLUME_GET_IFACE
+THUNAR_VFS_IS_VOLUME_CLASS
+THUNAR_VFS_VOLUME_GET_CLASS
 <SUBSECTION Private>
 thunar_vfs_volume_kind_get_type
 thunar_vfs_volume_status_get_type
@@ -418,18 +419,18 @@ thunar_vfs_volume_get_type
 <SECTION>
 <FILE>thunar-vfs-volume-manager</FILE>
 <TITLE>ThunarVfsVolumeManager</TITLE>
-ThunarVfsVolumeManagerIface
 ThunarVfsVolumeManager
 thunar_vfs_volume_manager_get_default
 thunar_vfs_volume_manager_get_volume_by_info
 thunar_vfs_volume_manager_get_volumes
-thunar_vfs_volume_manager_volumes_added
-thunar_vfs_volume_manager_volumes_removed
 <SUBSECTION Standard>
+ThunarVfsVolumeManagerClass
 THUNAR_VFS_TYPE_VOLUME_MANAGER
 THUNAR_VFS_VOLUME_MANAGER
+THUNAR_VFS_VOLUME_MANAGER_CLASS
 THUNAR_VFS_IS_VOLUME_MANAGER
-THUNAR_VFS_VOLUME_MANAGER_GET_IFACE
+THUNAR_VFS_IS_VOLUME_MANAGER_CLASS
+THUNAR_VFS_VOLUME_MANAGER_GET_CLASS
 <SUBSECTION Private>
 thunar_vfs_volume_manager_get_type
 </SECTION>
diff --git a/docs/reference/thunar-vfs/tmpl/thunar-vfs-volume-manager.sgml b/docs/reference/thunar-vfs/tmpl/thunar-vfs-volume-manager.sgml
index 7d8dcad9a..a291a9ad1 100644
--- a/docs/reference/thunar-vfs/tmpl/thunar-vfs-volume-manager.sgml
+++ b/docs/reference/thunar-vfs/tmpl/thunar-vfs-volume-manager.sgml
@@ -17,64 +17,77 @@ ThunarVfsVolumeManager
 <!-- ##### SECTION Stability_Level ##### -->
 
 
-<!-- ##### STRUCT ThunarVfsVolumeManagerIface ##### -->
+<!-- ##### STRUCT ThunarVfsVolumeManager ##### -->
 <para>
 
 </para>
 
-@get_volume_by_info: 
-@get_volumes: 
-@volumes_added: 
-@volumes_removed: 
+@volumes: 
 
-<!-- ##### STRUCT ThunarVfsVolumeManager ##### -->
+<!-- ##### SIGNAL ThunarVfsVolumeManager::volume-mounted ##### -->
 <para>
 
 </para>
 
+@thunarvfsvolumemanager: the object which received the signal.
+@arg1: 
 
-<!-- ##### FUNCTION thunar_vfs_volume_manager_get_default ##### -->
+<!-- ##### SIGNAL ThunarVfsVolumeManager::volume-pre-unmount ##### -->
 <para>
 
 </para>
 
-@Returns: 
+@thunarvfsvolumemanager: the object which received the signal.
+@arg1: 
 
+<!-- ##### SIGNAL ThunarVfsVolumeManager::volume-unmounted ##### -->
+<para>
 
-<!-- ##### FUNCTION thunar_vfs_volume_manager_get_volume_by_info ##### -->
+</para>
+
+@thunarvfsvolumemanager: the object which received the signal.
+@arg1: 
+
+<!-- ##### SIGNAL ThunarVfsVolumeManager::volumes-added ##### -->
 <para>
 
 </para>
 
-@manager: 
-@info: 
-@Returns: 
+@thunarvfsvolumemanager: the object which received the signal.
+@arg1: 
 
+<!-- ##### SIGNAL ThunarVfsVolumeManager::volumes-removed ##### -->
+<para>
 
-<!-- ##### FUNCTION thunar_vfs_volume_manager_get_volumes ##### -->
+</para>
+
+@thunarvfsvolumemanager: the object which received the signal.
+@arg1: 
+
+<!-- ##### FUNCTION thunar_vfs_volume_manager_get_default ##### -->
 <para>
 
 </para>
 
-@manager: 
 @Returns: 
 
 
-<!-- ##### FUNCTION thunar_vfs_volume_manager_volumes_added ##### -->
+<!-- ##### FUNCTION thunar_vfs_volume_manager_get_volume_by_info ##### -->
 <para>
 
 </para>
 
 @manager: 
-@volumes: 
+@info: 
+@Returns: 
 
 
-<!-- ##### FUNCTION thunar_vfs_volume_manager_volumes_removed ##### -->
+<!-- ##### FUNCTION thunar_vfs_volume_manager_get_volumes ##### -->
 <para>
 
 </para>
 
 @manager: 
-@volumes: 
+@Returns: 
 
 
diff --git a/docs/reference/thunar-vfs/tmpl/thunar-vfs-volume.sgml b/docs/reference/thunar-vfs/tmpl/thunar-vfs-volume.sgml
index ce5eed3c9..efb2c2dda 100644
--- a/docs/reference/thunar-vfs/tmpl/thunar-vfs-volume.sgml
+++ b/docs/reference/thunar-vfs/tmpl/thunar-vfs-volume.sgml
@@ -45,26 +45,39 @@ ThunarVfsVolume
 @THUNAR_VFS_VOLUME_STATUS_MOUNTED: 
 @THUNAR_VFS_VOLUME_STATUS_PRESENT: 
 
-<!-- ##### STRUCT ThunarVfsVolumeIface ##### -->
+<!-- ##### STRUCT ThunarVfsVolume ##### -->
 <para>
 
 </para>
 
-@get_kind: 
-@get_name: 
-@get_status: 
-@get_mount_point: 
-@lookup_icon_name: 
-@eject: 
-@mount: 
-@unmount: 
-@changed: 
 
-<!-- ##### STRUCT ThunarVfsVolume ##### -->
+<!-- ##### SIGNAL ThunarVfsVolume::changed ##### -->
+<para>
+
+</para>
+
+@thunarvfsvolume: the object which received the signal.
+
+<!-- ##### SIGNAL ThunarVfsVolume::mounted ##### -->
+<para>
+
+</para>
+
+@thunarvfsvolume: the object which received the signal.
+
+<!-- ##### SIGNAL ThunarVfsVolume::pre-unmount ##### -->
 <para>
 
 </para>
 
+@thunarvfsvolume: the object which received the signal.
+
+<!-- ##### SIGNAL ThunarVfsVolume::unmounted ##### -->
+<para>
+
+</para>
+
+@thunarvfsvolume: the object which received the signal.
 
 <!-- ##### FUNCTION thunar_vfs_volume_get_kind ##### -->
 <para>
@@ -181,11 +194,3 @@ ThunarVfsVolume
 @Returns: 
 
 
-<!-- ##### FUNCTION thunar_vfs_volume_changed ##### -->
-<para>
-
-</para>
-
-@volume: 
-
-
diff --git a/thunar-vfs/Makefile.am b/thunar-vfs/Makefile.am
index 3f87b95d6..b290e1abf 100644
--- a/thunar-vfs/Makefile.am
+++ b/thunar-vfs/Makefile.am
@@ -103,6 +103,8 @@ libthunar_vfs_1_la_SOURCES =						\
 	thunar-vfs-user.c						\
 	thunar-vfs-util.c						\
 	thunar-vfs-volume.c						\
+	thunar-vfs-volume-manager.c					\
+	thunar-vfs-volume-private.h					\
 	thunar-vfs-xfer.c						\
 	thunar-vfs-xfer.h						\
 	thunar-vfs.c
diff --git a/thunar-vfs/thunar-vfs-volume-freebsd.c b/thunar-vfs/thunar-vfs-volume-freebsd.c
index 851c47ed2..c00f68689 100644
--- a/thunar-vfs/thunar-vfs-volume-freebsd.c
+++ b/thunar-vfs/thunar-vfs-volume-freebsd.c
@@ -45,17 +45,14 @@
 #include <unistd.h>
 #endif
 
-#include <exo/exo.h>
-
 #include <thunar-vfs/thunar-vfs-exec.h>
 #include <thunar-vfs/thunar-vfs-volume-freebsd.h>
+#include <thunar-vfs/thunar-vfs-volume-private.h>
 #include <thunar-vfs/thunar-vfs-alias.h>
 
 
 
 static void                     thunar_vfs_volume_freebsd_class_init       (ThunarVfsVolumeFreeBSDClass *klass);
-static void                     thunar_vfs_volume_freebsd_volume_init      (ThunarVfsVolumeIface        *iface);
-static void                     thunar_vfs_volume_freebsd_init             (ThunarVfsVolumeFreeBSD      *volume_freebsd);
 static void                     thunar_vfs_volume_freebsd_finalize         (GObject                     *object);
 static ThunarVfsVolumeKind      thunar_vfs_volume_freebsd_get_kind         (ThunarVfsVolume             *volume);
 static const gchar             *thunar_vfs_volume_freebsd_get_name         (ThunarVfsVolume             *volume);
@@ -78,12 +75,12 @@ static ThunarVfsVolumeFreeBSD  *thunar_vfs_volume_freebsd_new              (cons
 
 struct _ThunarVfsVolumeFreeBSDClass
 {
-  GObjectClass __parent__;
+  ThunarVfsVolumeClass __parent__;
 };
 
 struct _ThunarVfsVolumeFreeBSD
 {
-  GObject __parent__;
+  ThunarVfsVolume       __parent__;
 
   gchar                *device_path;
   const gchar          *device_name;
@@ -102,42 +99,59 @@ struct _ThunarVfsVolumeFreeBSD
 
 
 
-G_DEFINE_TYPE_WITH_CODE (ThunarVfsVolumeFreeBSD,
-                         thunar_vfs_volume_freebsd,
-                         G_TYPE_OBJECT,
-                         G_IMPLEMENT_INTERFACE (THUNAR_VFS_TYPE_VOLUME,
-                                                thunar_vfs_volume_freebsd_volume_init));
+static GObjectClass *thunar_vfs_volume_freebsd_parent_class;
 
 
 
-static void
-thunar_vfs_volume_freebsd_class_init (ThunarVfsVolumeFreeBSDClass *klass)
+GType
+thunar_vfs_volume_freebsd_get_type (void)
 {
-  GObjectClass *gobject_class;
+  static GType type = G_TYPE_INVALID;
 
-  gobject_class = G_OBJECT_CLASS (klass);
-  gobject_class->finalize = thunar_vfs_volume_freebsd_finalize;
+  if (G_UNLIKELY (type == G_TYPE_INVALID))
+    {
+      static const GTypeInfo info =
+      {
+        sizeof (ThunarVfsVolumeFreeBSDClass),
+        NULL,
+        NULL,
+        (GClassInitFunc) thunar_vfs_volume_freebsd_class_init,
+        NULL,
+        NULL,
+        sizeof (ThunarVfsVolumeFreeBSD),
+        0,
+        NULL,
+        NULL,
+      };
+
+      type = g_type_register_static (THUNAR_VFS_TYPE_VOLUME, I_("ThunarVfsVolumeFreeBSD"), &info, 0);
+    }
+
+  return type;
 }
 
 
 
 static void
-thunar_vfs_volume_freebsd_volume_init (ThunarVfsVolumeIface *iface)
+thunar_vfs_volume_freebsd_class_init (ThunarVfsVolumeFreeBSDClass *klass)
 {
-  iface->get_kind = thunar_vfs_volume_freebsd_get_kind;
-  iface->get_name = thunar_vfs_volume_freebsd_get_name;
-  iface->get_status = thunar_vfs_volume_freebsd_get_status;
-  iface->get_mount_point = thunar_vfs_volume_freebsd_get_mount_point;
-  iface->eject = thunar_vfs_volume_freebsd_eject;
-  iface->mount = thunar_vfs_volume_freebsd_mount;
-  iface->unmount = thunar_vfs_volume_freebsd_unmount;
-}
+  ThunarVfsVolumeClass *thunarvfs_volume_class;
+  GObjectClass         *gobject_class;
 
+  /* determine the parent type class */
+  thunar_vfs_volume_freebsd_parent_class = g_type_class_peek_parent (klass);
 
+  gobject_class = G_OBJECT_CLASS (klass);
+  gobject_class->finalize = thunar_vfs_volume_freebsd_finalize;
 
-static void
-thunar_vfs_volume_freebsd_init (ThunarVfsVolumeFreeBSD *volume_freebsd)
-{
+  thunarvfs_volume_class = THUNAR_VFS_VOLUME_CLASS (klass);
+  thunarvfs_volume_class->get_kind = thunar_vfs_volume_freebsd_get_kind;
+  thunarvfs_volume_class->get_name = thunar_vfs_volume_freebsd_get_name;
+  thunarvfs_volume_class->get_status = thunar_vfs_volume_freebsd_get_status;
+  thunarvfs_volume_class->get_mount_point = thunar_vfs_volume_freebsd_get_mount_point;
+  thunarvfs_volume_class->eject = thunar_vfs_volume_freebsd_eject;
+  thunarvfs_volume_class->mount = thunar_vfs_volume_freebsd_mount;
+  thunarvfs_volume_class->unmount = thunar_vfs_volume_freebsd_unmount;
 }
 
 
@@ -147,9 +161,7 @@ thunar_vfs_volume_freebsd_finalize (GObject *object)
 {
   ThunarVfsVolumeFreeBSD *volume_freebsd = THUNAR_VFS_VOLUME_FREEBSD (object);
 
-  g_return_if_fail (THUNAR_VFS_IS_VOLUME_FREEBSD (volume_freebsd));
-
-  if (G_LIKELY (volume_freebsd->update_timer_id >= 0))
+  if (G_LIKELY (volume_freebsd->update_timer_id > 0))
     g_source_remove (volume_freebsd->update_timer_id);
 
   if (G_LIKELY (volume_freebsd->mount_point != NULL))
@@ -158,7 +170,7 @@ thunar_vfs_volume_freebsd_finalize (GObject *object)
   g_free (volume_freebsd->device_path);
   g_free (volume_freebsd->label);
 
-  G_OBJECT_CLASS (thunar_vfs_volume_freebsd_parent_class)->finalize (object);
+  (*G_OBJECT_CLASS (thunar_vfs_volume_freebsd_parent_class)->finalize) (object);
 }
 
 
@@ -175,7 +187,6 @@ static const gchar*
 thunar_vfs_volume_freebsd_get_name (ThunarVfsVolume *volume)
 {
   ThunarVfsVolumeFreeBSD *volume_freebsd = THUNAR_VFS_VOLUME_FREEBSD (volume);
-
   return (volume_freebsd->label != NULL) ? volume_freebsd->label : volume_freebsd->device_name;
 }
 
@@ -405,52 +416,60 @@ thunar_vfs_volume_freebsd_new (const gchar *device_path,
 
 
 static void             thunar_vfs_volume_manager_freebsd_class_init         (ThunarVfsVolumeManagerFreeBSDClass *klass);
-static void             thunar_vfs_volume_manager_freebsd_manager_init       (ThunarVfsVolumeManagerIface        *iface);
 static void             thunar_vfs_volume_manager_freebsd_init               (ThunarVfsVolumeManagerFreeBSD      *manager_freebsd);
-static void             thunar_vfs_volume_manager_freebsd_finalize           (GObject                            *object);
 static ThunarVfsVolume *thunar_vfs_volume_manager_freebsd_get_volume_by_info (ThunarVfsVolumeManager             *manager,
                                                                               const ThunarVfsInfo                *info);
-static GList           *thunar_vfs_volume_manager_freebsd_get_volumes        (ThunarVfsVolumeManager             *manager);
 
 
 
 struct _ThunarVfsVolumeManagerFreeBSDClass
 {
-  GObjectClass __parent__;
+  ThunarVfsVolumeManagerClass __parent__;
 };
 
 struct _ThunarVfsVolumeManagerFreeBSD
 {
-  GObject __parent__;
-  GList  *volumes;
+  ThunarVfsVolumeManager __parent__;
 };
 
 
 
-G_DEFINE_TYPE_WITH_CODE (ThunarVfsVolumeManagerFreeBSD,
-                         thunar_vfs_volume_manager_freebsd,
-                         G_TYPE_OBJECT,
-                         G_IMPLEMENT_INTERFACE (THUNAR_VFS_TYPE_VOLUME_MANAGER,
-                                                thunar_vfs_volume_manager_freebsd_manager_init));
-
-
-
-static void
-thunar_vfs_volume_manager_freebsd_class_init (ThunarVfsVolumeManagerFreeBSDClass *klass)
+GType
+thunar_vfs_volume_manager_freebsd_get_type (void)
 {
-  GObjectClass *gobject_class;
+  static GType type = G_TYPE_INVALID;
 
-  gobject_class = G_OBJECT_CLASS (klass);
-  gobject_class->finalize = thunar_vfs_volume_manager_freebsd_finalize;
+  if (G_UNLIKELY (type == G_TYPE_INVALID))
+    {
+      static const GTypeInfo info =
+      {
+        sizeof (ThunarVfsVolumeManagerFreeBSDClass),
+        NULL,
+        NULL,
+        (GClassInitFunc) thunar_vfs_volume_manager_freebsd_class_init,
+        NULL,
+        NULL,
+        sizeof (ThunarVfsVolumeManagerFreeBSD),
+        0,
+        (GInstanceInitFunc) thunar_vfs_volume_manager_freebsd_init,
+        NULL,
+      };
+
+      type = g_type_register_static (THUNAR_VFS_TYPE_VOLUME_MANAGER, I_("ThunarVfsVolumeManagerFreeBSD"), &info, 0);
+    }
+
+  return type;
 }
 
 
 
 static void
-thunar_vfs_volume_manager_freebsd_manager_init (ThunarVfsVolumeManagerIface *iface)
+thunar_vfs_volume_manager_freebsd_class_init (ThunarVfsVolumeManagerFreeBSDClass *klass)
 {
-  iface->get_volume_by_info = thunar_vfs_volume_manager_freebsd_get_volume_by_info;
-  iface->get_volumes = thunar_vfs_volume_manager_freebsd_get_volumes;
+  ThunarVfsVolumeManagerClass *thunarvfs_volume_manager_class;
+
+  thunarvfs_volume_manager_class = THUNAR_VFS_VOLUME_MANAGER_CLASS (klass);
+  thunarvfs_volume_manager_class->get_volume_by_info = thunar_vfs_volume_manager_freebsd_get_volume_by_info;
 }
 
 
@@ -480,7 +499,10 @@ thunar_vfs_volume_manager_freebsd_init (ThunarVfsVolumeManagerFreeBSD *manager_f
 
       volume_freebsd = thunar_vfs_volume_freebsd_new (fs->fs_spec, fs->fs_file);
       if (G_LIKELY (volume_freebsd != NULL))
-        manager_freebsd->volumes = g_list_append (manager_freebsd->volumes, volume_freebsd);
+        {
+          thunar_vfs_volume_manager_add (THUNAR_VFS_VOLUME_MANAGER (manager_freebsd), THUNAR_VFS_VOLUME (volume_freebsd));
+          g_object_unref (G_OBJECT (volume_freebsd));
+        }
     }
 
   /* unload the fstab database */
@@ -489,32 +511,14 @@ thunar_vfs_volume_manager_freebsd_init (ThunarVfsVolumeManagerFreeBSD *manager_f
 
 
 
-static void
-thunar_vfs_volume_manager_freebsd_finalize (GObject *object)
-{
-  ThunarVfsVolumeManagerFreeBSD *manager_freebsd = THUNAR_VFS_VOLUME_MANAGER_FREEBSD (object);
-  GList                         *lp;
-
-  g_return_if_fail (THUNAR_VFS_IS_VOLUME_MANAGER (manager_freebsd));
-
-  for (lp = manager_freebsd->volumes; lp != NULL; lp = lp->next)
-    g_object_unref (G_OBJECT (lp->data));
-  g_list_free (manager_freebsd->volumes);
-
-  G_OBJECT_CLASS (thunar_vfs_volume_manager_freebsd_parent_class)->finalize (object);
-}
-
-
-
 static ThunarVfsVolume*
 thunar_vfs_volume_manager_freebsd_get_volume_by_info (ThunarVfsVolumeManager *manager,
-                                                  const ThunarVfsInfo    *info)
+                                                      const ThunarVfsInfo    *info)
 {
-  ThunarVfsVolumeManagerFreeBSD *manager_freebsd = THUNAR_VFS_VOLUME_MANAGER_FREEBSD (manager);
-  ThunarVfsVolumeFreeBSD        *volume_freebsd = NULL;
-  GList                         *lp;
+  ThunarVfsVolumeFreeBSD *volume_freebsd = NULL;
+  GList                  *lp;
 
-  for (lp = manager_freebsd->volumes; lp != NULL; lp = lp->next)
+  for (lp = manager->volumes; lp != NULL; lp = lp->next)
     {
       volume_freebsd = THUNAR_VFS_VOLUME_FREEBSD (lp->data);
       if ((volume_freebsd->status & THUNAR_VFS_VOLUME_STATUS_MOUNTED) != 0 && volume_freebsd->device_id == info->device)
@@ -526,12 +530,5 @@ thunar_vfs_volume_manager_freebsd_get_volume_by_info (ThunarVfsVolumeManager *ma
 
 
 
-static GList*
-thunar_vfs_volume_manager_freebsd_get_volumes (ThunarVfsVolumeManager *manager)
-{
-  return THUNAR_VFS_VOLUME_MANAGER_FREEBSD (manager)->volumes;
-}
-
-
-
-
+#define __THUNAR_VFS_VOLUME_FREEBSD_C__
+#include <thunar-vfs/thunar-vfs-aliasdef.c>
diff --git a/thunar-vfs/thunar-vfs-volume-hal.c b/thunar-vfs/thunar-vfs-volume-hal.c
index 2047c1d37..fe6b6be5a 100644
--- a/thunar-vfs/thunar-vfs-volume-hal.c
+++ b/thunar-vfs/thunar-vfs-volume-hal.c
@@ -35,19 +35,16 @@
 
 #include <dbus/dbus-glib-lowlevel.h>
 
-#include <exo/exo.h>
-
 #include <libhal.h>
 #include <libhal-storage.h>
 
 #include <thunar-vfs/thunar-vfs-volume-hal.h>
+#include <thunar-vfs/thunar-vfs-volume-private.h>
 #include <thunar-vfs/thunar-vfs-alias.h>
 
 
 
 static void                  thunar_vfs_volume_hal_class_init       (ThunarVfsVolumeHalClass *klass);
-static void                  thunar_vfs_volume_hal_volume_init      (ThunarVfsVolumeIface    *iface);
-static void                  thunar_vfs_volume_hal_init             (ThunarVfsVolumeHal      *volume_hal);
 static void                  thunar_vfs_volume_hal_finalize         (GObject                 *object);
 static ThunarVfsVolumeKind   thunar_vfs_volume_hal_get_kind         (ThunarVfsVolume         *volume);
 static const gchar          *thunar_vfs_volume_hal_get_name         (ThunarVfsVolume         *volume);
@@ -62,6 +59,8 @@ static gboolean              thunar_vfs_volume_hal_mount            (ThunarVfsVo
 static gboolean              thunar_vfs_volume_hal_unmount          (ThunarVfsVolume         *volume,
                                                                      GtkWidget               *window,
                                                                      GError                 **error);
+static ThunarVfsPath        *thunar_vfs_volume_hal_find_mount_point (ThunarVfsVolumeHal      *volume_hal,
+                                                                     const gchar             *file);
 static void                  thunar_vfs_volume_hal_update           (ThunarVfsVolumeHal      *volume_hal,
                                                                      LibHalContext           *context,
                                                                      LibHalVolume            *hv,
@@ -71,12 +70,12 @@ static void                  thunar_vfs_volume_hal_update           (ThunarVfsVo
 
 struct _ThunarVfsVolumeHalClass
 {
-  GObjectClass __parent__;
+  ThunarVfsVolumeClass __parent__;
 };
 
 struct _ThunarVfsVolumeHal
 {
-  GObject __parent__;
+  ThunarVfsVolume       __parent__;
 
   gchar                *udi;
   gchar                *drive_udi;
@@ -90,42 +89,59 @@ struct _ThunarVfsVolumeHal
 
 
 
-G_DEFINE_TYPE_WITH_CODE (ThunarVfsVolumeHal,
-                         thunar_vfs_volume_hal,
-                         G_TYPE_OBJECT,
-                         G_IMPLEMENT_INTERFACE (THUNAR_VFS_TYPE_VOLUME,
-                                                thunar_vfs_volume_hal_volume_init));
+static GObjectClass *thunar_vfs_volume_hal_parent_class;
 
 
 
-static void
-thunar_vfs_volume_hal_class_init (ThunarVfsVolumeHalClass *klass)
+GType
+thunar_vfs_volume_hal_get_type (void)
 {
-  GObjectClass *gobject_class;
+  static GType type = G_TYPE_INVALID;
 
-  gobject_class = G_OBJECT_CLASS (klass);
-  gobject_class->finalize = thunar_vfs_volume_hal_finalize;
+  if (G_UNLIKELY (type == G_TYPE_INVALID))
+    {
+      static const GTypeInfo info =
+      {
+        sizeof (ThunarVfsVolumeHalClass),
+        NULL,
+        NULL,
+        (GClassInitFunc) thunar_vfs_volume_hal_class_init,
+        NULL,
+        NULL,
+        sizeof (ThunarVfsVolumeHal),
+        0,
+        NULL,
+        NULL,
+      };
+
+      type = g_type_register_static (THUNAR_VFS_TYPE_VOLUME, I_("ThunarVfsVolumeHal"), &info, 0);
+    }
+
+  return type;
 }
 
 
 
 static void
-thunar_vfs_volume_hal_volume_init (ThunarVfsVolumeIface *iface)
+thunar_vfs_volume_hal_class_init (ThunarVfsVolumeHalClass *klass)
 {
-  iface->get_kind = thunar_vfs_volume_hal_get_kind;
-  iface->get_name = thunar_vfs_volume_hal_get_name;
-  iface->get_status = thunar_vfs_volume_hal_get_status;
-  iface->get_mount_point = thunar_vfs_volume_hal_get_mount_point;
-  iface->eject = thunar_vfs_volume_hal_eject;
-  iface->mount = thunar_vfs_volume_hal_mount;
-  iface->unmount = thunar_vfs_volume_hal_unmount;
-}
+  ThunarVfsVolumeClass *thunarvfs_volume_class;
+  GObjectClass         *gobject_class;
 
+  /* determine the parent type class */
+  thunar_vfs_volume_hal_parent_class = g_type_class_peek_parent (klass);
 
+  gobject_class = G_OBJECT_CLASS (klass);
+  gobject_class->finalize = thunar_vfs_volume_hal_finalize;
 
-static void
-thunar_vfs_volume_hal_init (ThunarVfsVolumeHal *volume_hal)
-{
+  thunarvfs_volume_class = THUNAR_VFS_VOLUME_CLASS (klass);
+  thunarvfs_volume_class->get_kind = thunar_vfs_volume_hal_get_kind;
+  thunarvfs_volume_class->get_name = thunar_vfs_volume_hal_get_name;
+  thunarvfs_volume_class->get_status = thunar_vfs_volume_hal_get_status;
+  thunarvfs_volume_class->get_mount_point = thunar_vfs_volume_hal_get_mount_point;
+  thunarvfs_volume_class->eject = thunar_vfs_volume_hal_eject;
+  thunarvfs_volume_class->mount = thunar_vfs_volume_hal_mount;
+  thunarvfs_volume_class->unmount = thunar_vfs_volume_hal_unmount;
 }
 
 
@@ -254,13 +270,11 @@ thunar_vfs_volume_hal_mount (ThunarVfsVolume *volume,
 {
   ThunarVfsVolumeHal *volume_hal = THUNAR_VFS_VOLUME_HAL (volume);
   ThunarVfsPath      *path;
-  struct mntent      *mntent;
   gboolean            result;
   gchar              *standard_error;
   gchar              *command_line;
   gchar              *mount_point;
   gchar              *quoted;
-  FILE               *fp;
   gint                exit_status;
 
   /* generate the mount command */
@@ -352,53 +366,23 @@ thunar_vfs_volume_hal_mount (ThunarVfsVolume *volume,
   if (G_LIKELY (result))
     {
       /* try to figure out where the device was mounted */
-      fp = setmntent ("/proc/mounts", "r");
-      if (G_LIKELY (fp != NULL))
+      path = thunar_vfs_volume_hal_find_mount_point (volume_hal, "/proc/mounts");
+      if (G_LIKELY (path != NULL))
         {
-          /* assume that we failed */
-          result = FALSE;
+          /* we must have been mounted successfully */
+          volume_hal->status |= THUNAR_VFS_VOLUME_STATUS_MOUNTED | THUNAR_VFS_VOLUME_STATUS_PRESENT;
 
-          /* lookup the mount entry for our device */
-          for (;;)
-            {
-              /* read the next entry */
-              mntent = getmntent (fp);
-              if (mntent == NULL)
-                break;
-
-              /* check if this is the entry we are looking for */
-              if (exo_str_is_equal (mntent->mnt_fsname, volume_hal->device_file))
-                {
-                  /* transform the mount point to a path */
-                  path = thunar_vfs_path_new (mntent->mnt_dir, NULL);
-                  if (G_LIKELY (path != NULL))
-                    {
-                      /* we must have been mounted successfully */
-                      volume_hal->status |= THUNAR_VFS_VOLUME_STATUS_MOUNTED | THUNAR_VFS_VOLUME_STATUS_PRESENT;
-                      result = TRUE;
-
-                      /* replace the existing mount point */
-                      thunar_vfs_path_unref (volume_hal->mount_point);
-                      volume_hal->mount_point = path;
-
-                      /* tell everybody that we have a new state */
-                      thunar_vfs_volume_changed (THUNAR_VFS_VOLUME (volume_hal));
-                    }
-                  break;
-                }
-            }
+          /* replace the existing mount point */
+          thunar_vfs_path_unref (volume_hal->mount_point);
+          volume_hal->mount_point = path;
 
-          /* check if we were unable to figure out the mount point */
-          if (G_UNLIKELY (!result))
-            g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("Failed to determine the mount point for %s"), volume_hal->device_file);
-
-          /* close the file handle */
-          fclose (fp);
+          /* tell everybody that we have a new state */
+          thunar_vfs_volume_changed (THUNAR_VFS_VOLUME (volume_hal));
         }
       else
         {
-          /* if we cannot read /proc/mounts, we cannot where the volume was mounted */
-          g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno), _("Failed to open /proc/mounts: %s"), g_strerror (errno));
+          /* something went wrong, for sure */
+          g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("Failed to determine the mount point for %s"), volume_hal->device_file);
           result = FALSE;
         }
     }
@@ -519,6 +503,43 @@ thunar_vfs_volume_hal_unmount (ThunarVfsVolume *volume,
 
 
 
+static ThunarVfsPath*
+thunar_vfs_volume_hal_find_mount_point (ThunarVfsVolumeHal *volume_hal,
+                                        const gchar        *file)
+{
+  ThunarVfsPath *mount_point = NULL;
+  struct mntent *mntent;
+  FILE          *fp;
+
+  /* try to open that file as mnt entry list */
+  fp = setmntent (file, "r");
+  if (G_LIKELY (fp != NULL))
+    {
+      /* process all mnt entries */
+      while (mount_point == NULL)
+        {
+          /* read the next entry */
+          mntent = getmntent (fp);
+          if (mntent == NULL)
+            break;
+
+          /* check if this is the entry we are looking for */
+          if (exo_str_is_equal (mntent->mnt_fsname, volume_hal->device_file))
+            {
+              /* and there's our mount point */
+              mount_point = thunar_vfs_path_new (mntent->mnt_dir, NULL);
+            }
+        }
+
+      /* close the file handle */
+      endmntent (fp);
+    }
+
+  return mount_point;
+}
+
+
+
 static void
 thunar_vfs_volume_hal_update (ThunarVfsVolumeHal *volume_hal,
                               LibHalContext      *context,
@@ -526,13 +547,11 @@ thunar_vfs_volume_hal_update (ThunarVfsVolumeHal *volume_hal,
                               LibHalDrive        *hd)
 {
   LibHalStoragePolicy *policy;
-  struct mntent       *mntent;
   const gchar         *desired_mount_point;
   const gchar         *volume_label;
   gchar               *mount_root;
   gchar               *basename;
   gchar               *filename;
-  FILE                *fp;
 
   g_return_if_fail (THUNAR_VFS_IS_VOLUME_HAL (volume_hal));
   g_return_if_fail (hv != NULL);
@@ -656,6 +675,15 @@ thunar_vfs_volume_hal_update (ThunarVfsVolumeHal *volume_hal,
       if (G_LIKELY (volume_hal->mount_point != NULL))
         volume_hal->status |= THUNAR_VFS_VOLUME_STATUS_MOUNTED | THUNAR_VFS_VOLUME_STATUS_PRESENT;
     }
+  else
+    {
+      /* we don't trust HAL, so let's see what /proc/mounts says about the volume */
+      volume_hal->mount_point = thunar_vfs_volume_hal_find_mount_point (volume_hal, "/proc/mounts");
+
+      /* we must have been mounted successfully if we have a mount point */
+      if (G_LIKELY (volume_hal->mount_point != NULL))
+        volume_hal->status |= THUNAR_VFS_VOLUME_STATUS_MOUNTED | THUNAR_VFS_VOLUME_STATUS_PRESENT;
+    }
 
   /* check if we have to figure out the mount point ourself */
   if (G_UNLIKELY (volume_hal->mount_point == NULL))
@@ -670,29 +698,7 @@ thunar_vfs_volume_hal_update (ThunarVfsVolumeHal *volume_hal,
         }
 
       /* lets see, maybe /etc/fstab knows where to mount */
-      fp = setmntent ("/etc/fstab", "r");
-      if (G_LIKELY (fp != NULL))
-        {
-          /* check all entries */
-          for (;;)
-            {
-              /* read the next entry */
-              mntent = getmntent (fp);
-              if (mntent == NULL)
-                break;
-
-              /* check if the entry is for our device */
-              if (exo_str_is_equal (mntent->mnt_fsname, volume_hal->device_file))
-                {
-                  /* transform to a path object */
-                  volume_hal->mount_point = thunar_vfs_path_new (mntent->mnt_dir, NULL);
-                  break;
-                }
-            }
-
-          /* close the /etc/fstab file handle */
-          endmntent (fp);
-        }
+      volume_hal->mount_point = thunar_vfs_volume_hal_find_mount_point (volume_hal, "/etc/fstab");
 
       /* if we still don't have a mount point, ask HAL */
       if (G_UNLIKELY (volume_hal->mount_point == NULL))
@@ -736,12 +742,8 @@ thunar_vfs_volume_hal_update (ThunarVfsVolumeHal *volume_hal,
 
 
 static void                thunar_vfs_volume_manager_hal_class_init               (ThunarVfsVolumeManagerHalClass *klass);
-static void                thunar_vfs_volume_manager_hal_manager_init             (ThunarVfsVolumeManagerIface    *iface);
 static void                thunar_vfs_volume_manager_hal_init                     (ThunarVfsVolumeManagerHal      *manager_hal);
 static void                thunar_vfs_volume_manager_hal_finalize                 (GObject                        *object);
-static ThunarVfsVolume    *thunar_vfs_volume_manager_hal_get_volume_by_info       (ThunarVfsVolumeManager         *manager,
-                                                                                   const ThunarVfsInfo            *info);
-static GList              *thunar_vfs_volume_manager_hal_get_volumes              (ThunarVfsVolumeManager         *manager);
 static ThunarVfsVolumeHal *thunar_vfs_volume_manager_hal_get_volume_by_udi        (ThunarVfsVolumeManagerHal      *manager_hal,
                                                                                    const gchar                    *udi);
 static void                thunar_vfs_volume_manager_hal_update_volume_by_udi     (ThunarVfsVolumeManagerHal      *manager_hal,
@@ -766,43 +768,62 @@ static void                thunar_vfs_volume_manager_hal_device_property_modifie
 
 struct _ThunarVfsVolumeManagerHalClass
 {
-  GObjectClass __parent__;
+  ThunarVfsVolumeManagerClass __parent__;
 };
 
 struct _ThunarVfsVolumeManagerHal
 {
-  GObject         __parent__;
-  DBusConnection *dbus_connection;
-  LibHalContext  *context;
-  GList          *volumes;
+  ThunarVfsVolumeManager __parent__;
+  DBusConnection        *dbus_connection;
+  LibHalContext         *context;
+  GList                 *volumes;
 };
 
 
 
-G_DEFINE_TYPE_WITH_CODE (ThunarVfsVolumeManagerHal,
-                         thunar_vfs_volume_manager_hal,
-                         G_TYPE_OBJECT,
-                         G_IMPLEMENT_INTERFACE (THUNAR_VFS_TYPE_VOLUME_MANAGER,
-                                                thunar_vfs_volume_manager_hal_manager_init));
+static GObjectClass *thunar_vfs_volume_manager_hal_parent_class;
 
 
 
-static void
-thunar_vfs_volume_manager_hal_class_init (ThunarVfsVolumeManagerHalClass *klass)
+GType
+thunar_vfs_volume_manager_hal_get_type (void)
 {
-  GObjectClass *gobject_class;
+  static GType type = G_TYPE_INVALID;
 
-  gobject_class = G_OBJECT_CLASS (klass);
-  gobject_class->finalize = thunar_vfs_volume_manager_hal_finalize;
+  if (G_UNLIKELY (type == G_TYPE_INVALID))
+    {
+      static const GTypeInfo info =
+      {
+        sizeof (ThunarVfsVolumeManagerHalClass),
+        NULL,
+        NULL,
+        (GClassInitFunc) thunar_vfs_volume_manager_hal_class_init,
+        NULL,
+        NULL,
+        sizeof (ThunarVfsVolumeManagerHal),
+        0,
+        (GInstanceInitFunc) thunar_vfs_volume_manager_hal_init,
+        NULL,
+      };
+
+      type = g_type_register_static (THUNAR_VFS_TYPE_VOLUME_MANAGER, I_("ThunarVfsVolumeManagerHal"), &info, 0);
+    }
+
+  return type;
 }
 
 
 
 static void
-thunar_vfs_volume_manager_hal_manager_init (ThunarVfsVolumeManagerIface *iface)
+thunar_vfs_volume_manager_hal_class_init (ThunarVfsVolumeManagerHalClass *klass)
 {
-  iface->get_volume_by_info = thunar_vfs_volume_manager_hal_get_volume_by_info;
-  iface->get_volumes = thunar_vfs_volume_manager_hal_get_volumes;
+  GObjectClass *gobject_class;
+
+  /* determine the parent type class */
+  thunar_vfs_volume_manager_hal_parent_class = g_type_class_peek_parent (klass);
+
+  gobject_class = G_OBJECT_CLASS (klass);
+  gobject_class->finalize = thunar_vfs_volume_manager_hal_finalize;
 }
 
 
@@ -940,31 +961,13 @@ thunar_vfs_volume_manager_hal_finalize (GObject *object)
 
 
 
-static ThunarVfsVolume*
-thunar_vfs_volume_manager_hal_get_volume_by_info (ThunarVfsVolumeManager *manager,
-                                                  const ThunarVfsInfo    *info)
-{
-  // FIXME: No idea how to implement this on Linux right now.
-  return NULL;
-}
-
-
-
-static GList*
-thunar_vfs_volume_manager_hal_get_volumes (ThunarVfsVolumeManager *manager)
-{
-  return THUNAR_VFS_VOLUME_MANAGER_HAL (manager)->volumes;
-}
-
-
-
 static ThunarVfsVolumeHal*
 thunar_vfs_volume_manager_hal_get_volume_by_udi (ThunarVfsVolumeManagerHal *manager_hal,
                                                  const gchar               *udi)
 {
   GList *lp;
 
-  for (lp = manager_hal->volumes; lp != NULL; lp = lp->next)
+  for (lp = THUNAR_VFS_VOLUME_MANAGER (manager_hal)->volumes; lp != NULL; lp = lp->next)
     if (exo_str_is_equal (THUNAR_VFS_VOLUME_HAL (lp->data)->udi, udi))
       return THUNAR_VFS_VOLUME_HAL (lp->data);
 
@@ -1034,7 +1037,6 @@ thunar_vfs_volume_manager_hal_device_added (LibHalContext *context,
   LibHalVolume              *hv;
   LibHalDrive               *hd;
   const gchar               *drive_udi;
-  GList                      volume_list;
 
   g_return_if_fail (THUNAR_VFS_IS_VOLUME_MANAGER_HAL (manager_hal));
   g_return_if_fail (manager_hal->context == context);
@@ -1073,16 +1075,13 @@ thunar_vfs_volume_manager_hal_device_added (LibHalContext *context,
           thunar_vfs_volume_hal_update (volume_hal, context, hv, hd);
 
           /* add the volume object to our list if we allocated a new one */
-          if (g_list_find (manager_hal->volumes, volume_hal) == NULL)
+          if (g_list_find (THUNAR_VFS_VOLUME_MANAGER (manager_hal)->volumes, volume_hal) == NULL)
             {
-              /* just prepend the volume object... */
-              manager_hal->volumes = g_list_prepend (manager_hal->volumes, volume_hal);
-
-              /* ...and emit "volumes-added" */
-              volume_list.data = volume_hal;
-              volume_list.next = NULL;
-              volume_list.prev = NULL;
-              thunar_vfs_volume_manager_volumes_added (THUNAR_VFS_VOLUME_MANAGER (manager_hal), &volume_list);
+              /* add the volume to the volume manager */
+              thunar_vfs_volume_manager_add (THUNAR_VFS_VOLUME_MANAGER (manager_hal), THUNAR_VFS_VOLUME (volume_hal));
+
+              /* release the reference on the volume */
+              g_object_unref (G_OBJECT (volume_hal));
             }
 
           /* release the HAL drive */
@@ -1102,7 +1101,6 @@ thunar_vfs_volume_manager_hal_device_removed (LibHalContext *context,
 {
   ThunarVfsVolumeManagerHal *manager_hal = libhal_ctx_get_user_data (context);
   ThunarVfsVolumeHal        *volume_hal;
-  GList                      volume_list;
 
   g_return_if_fail (THUNAR_VFS_IS_VOLUME_MANAGER_HAL (manager_hal));
   g_return_if_fail (manager_hal->context == context);
@@ -1111,17 +1109,8 @@ thunar_vfs_volume_manager_hal_device_removed (LibHalContext *context,
   volume_hal = thunar_vfs_volume_manager_hal_get_volume_by_udi (manager_hal, udi);
   if (G_LIKELY (volume_hal != NULL))
     {
-      /* remove that volume from our list */
-      manager_hal->volumes = g_list_remove (manager_hal->volumes, volume_hal);
-
-      /* tell listeners that we dropped the volume */
-      volume_list.data = volume_hal;
-      volume_list.next = NULL;
-      volume_list.prev = NULL;
-      thunar_vfs_volume_manager_volumes_removed (THUNAR_VFS_VOLUME_MANAGER (manager_hal), &volume_list);
-
-      /* drop our reference on the volume */
-      g_object_unref (G_OBJECT (volume_hal));
+      /* remove the volume from the volume manager */
+      thunar_vfs_volume_manager_remove (THUNAR_VFS_VOLUME_MANAGER (manager_hal), THUNAR_VFS_VOLUME (volume_hal));
     }
 }
 
@@ -1177,4 +1166,5 @@ thunar_vfs_volume_manager_hal_device_property_modified (LibHalContext *context,
 
 
 
-
+#define __THUNAR_VFS_VOLUME_HAL_C__
+#include <thunar-vfs/thunar-vfs-aliasdef.c>
diff --git a/thunar-vfs/thunar-vfs-volume-manager.c b/thunar-vfs/thunar-vfs-volume-manager.c
new file mode 100644
index 000000000..1119bdfb8
--- /dev/null
+++ b/thunar-vfs/thunar-vfs-volume-manager.c
@@ -0,0 +1,488 @@
+/* $Id$ */
+/*-
+ * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <thunar-vfs/thunar-vfs-enum-types.h>
+#include <thunar-vfs/thunar-vfs-volume-freebsd.h>
+#include <thunar-vfs/thunar-vfs-volume-hal.h>
+#include <thunar-vfs/thunar-vfs-volume-none.h>
+#include <thunar-vfs/thunar-vfs-volume-private.h>
+#include <thunar-vfs/thunar-vfs-alias.h>
+
+
+
+/* determine the default thunar vfs volume manager type */
+#if defined(THUNAR_VFS_VOLUME_IMPL_FREEBSD)
+#define THUNAR_VFS_TYPE_VOLUME_MANAGER_IMPL THUNAR_VFS_TYPE_VOLUME_MANAGER_FREEBSD
+#elif defined(THUNAR_VFS_VOLUME_IMPL_HAL)
+#define THUNAR_VFS_TYPE_VOLUME_MANAGER_IMPL THUNAR_VFS_TYPE_VOLUME_MANAGER_HAL
+#elif defined(THUNAR_VFS_VOLUME_IMPL_NONE)
+#define THUNAR_VFS_TYPE_VOLUME_MANAGER_IMPL THUNAR_VFS_TYPE_VOLUME_MANAGER_NONE
+#else
+#error "Add your volume manager implemenation here!"
+#endif
+
+
+
+/* Signal identifiers */
+enum
+{
+  VOLUMES_ADDED,
+  VOLUMES_REMOVED,
+  VOLUME_MOUNTED,
+  VOLUME_PRE_UNMOUNT,
+  VOLUME_UNMOUNTED,
+  LAST_SIGNAL,
+};
+
+
+
+static void             thunar_vfs_volume_manager_class_init              (ThunarVfsVolumeManagerClass  *klass);
+static void             thunar_vfs_volume_manager_finalize                (GObject                      *object);
+static ThunarVfsVolume *thunar_vfs_volume_manager_real_get_volume_by_info (ThunarVfsVolumeManager       *manager, 
+                                                                           const ThunarVfsInfo          *info);
+static void             thunar_vfs_volume_manager_volume_mounted          (ThunarVfsVolumeManager       *manager,
+                                                                           ThunarVfsVolume              *volume);
+static void             thunar_vfs_volume_manager_volume_pre_unmount      (ThunarVfsVolumeManager       *manager,
+                                                                           ThunarVfsVolume              *volume);
+static void             thunar_vfs_volume_manager_volume_unmounted        (ThunarVfsVolumeManager       *manager,
+                                                                           ThunarVfsVolume              *volume);
+
+
+
+static GObjectClass *thunar_vfs_volume_manager_parent_class;
+static guint         manager_signals[LAST_SIGNAL];
+
+
+
+GType
+thunar_vfs_volume_manager_get_type (void)
+{
+  static GType type = G_TYPE_INVALID;
+
+  if (G_UNLIKELY (type == G_TYPE_INVALID))
+    {
+      static const GTypeInfo info =
+      {
+        sizeof (ThunarVfsVolumeManagerClass),
+        NULL,
+        NULL,
+        (GClassInitFunc) thunar_vfs_volume_manager_class_init,
+        NULL,
+        NULL,
+        sizeof (ThunarVfsVolumeManager),
+        0,
+        NULL,
+      };
+
+      type = g_type_register_static (G_TYPE_OBJECT, I_("ThunarVfsVolumeManager"), &info, G_TYPE_FLAG_ABSTRACT);
+    }
+
+  return type;
+}
+
+
+
+static void
+thunar_vfs_volume_manager_class_init (ThunarVfsVolumeManagerClass *klass)
+{
+  GObjectClass *gobject_class;
+
+  /* determine the parent type class */
+  thunar_vfs_volume_manager_parent_class = g_type_class_peek_parent (klass);
+
+  gobject_class = G_OBJECT_CLASS (klass);
+  gobject_class->finalize = thunar_vfs_volume_manager_finalize;
+
+  /* we provide a fallback implementation */
+  klass->get_volume_by_info = thunar_vfs_volume_manager_real_get_volume_by_info;
+
+  /**
+   * ThunarVfsVolumeManager::volumes-added:
+   * @manager : a #ThunarVfsVolumeManager instance.
+   * @volumes : a list of #ThunarVfsVolume<!---->s.
+   *
+   * Invoked by the @manager whenever new volumes have been
+   * attached to the system or the administrator changes the
+   * /etc/fstab file, or some other condition, depending
+   * on the manager implementation.
+   *
+   * Note that the implementation should not invoke this
+   * method when a volume is mounted, as that's a completely
+   * different condition!
+   **/
+  manager_signals[VOLUMES_ADDED] =
+    g_signal_new (I_("volumes-added"),
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (ThunarVfsVolumeManagerClass, volumes_added),
+                  NULL, NULL,
+                  g_cclosure_marshal_VOID__POINTER,
+                  G_TYPE_NONE, 1, G_TYPE_POINTER);
+
+  /**
+   * ThunarVfsVolumeManager::volumes-removed:
+   * @manager : a #ThunarVfsVolumeManager instance.
+   * @volumes : a list of #ThunarVfsVolume<!---->s.
+   *
+   * Invoked whenever the @manager notices that @volumes have
+   * been detached from the system.
+   **/
+  manager_signals[VOLUMES_REMOVED] =
+    g_signal_new (I_("volumes-removed"),
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (ThunarVfsVolumeManagerClass, volumes_removed),
+                  NULL, NULL,
+                  g_cclosure_marshal_VOID__POINTER,
+                  G_TYPE_NONE, 1, G_TYPE_POINTER);
+
+  /**
+   * ThunarVfsVolumeManager::volume-mounted:
+   * @manager : a #ThunarVfsVolumeManager instance.
+   * @volume  : a #ThunarVfsVolume instance.
+   *
+   * Emitted by @manager right after the @volume was
+   * successfully mounted.
+   **/
+  manager_signals[VOLUME_MOUNTED] =
+    g_signal_new (I_("volume-mounted"),
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (ThunarVfsVolumeManagerClass, volume_mounted),
+                  NULL, NULL,
+                  g_cclosure_marshal_VOID__OBJECT,
+                  G_TYPE_NONE, 1, THUNAR_VFS_TYPE_VOLUME);
+
+  /**
+   * ThunarVfsVolumeManager::volume-pre-unmount:
+   * @manager : a #ThunarVfsVolumeManager instance.
+   * @volume  : a #ThunarVfsVolume instance.
+   *
+   * Emitted by @manager right before an attempt is
+   * made to unmount @volume. Applications can connect
+   * to this signal to perform cleanups, like changing
+   * to a different folder if a folder on the @volume
+   * is currently displayed.
+   **/
+  manager_signals[VOLUME_PRE_UNMOUNT] =
+    g_signal_new (I_("volume-pre-unmount"),
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (ThunarVfsVolumeManagerClass, volume_pre_unmount),
+                  NULL, NULL,
+                  g_cclosure_marshal_VOID__OBJECT,
+                  G_TYPE_NONE, 1, THUNAR_VFS_TYPE_VOLUME);
+
+  /**
+   * ThunarVfsVolumeManager::volume-unmounted:
+   * @manager : a #ThunarVfsVolumeManager instance.
+   * @volume  : a #ThunarVfsVolume instance.
+   *
+   * Emitted by @manager right after the @volume was
+   * successfully unmounted.
+   **/
+  manager_signals[VOLUME_UNMOUNTED] =
+    g_signal_new (I_("volume-unmounted"),
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (ThunarVfsVolumeManagerClass, volume_unmounted),
+                  NULL, NULL,
+                  g_cclosure_marshal_VOID__OBJECT,
+                  G_TYPE_NONE, 1, THUNAR_VFS_TYPE_VOLUME);
+}
+
+
+
+static void
+thunar_vfs_volume_manager_finalize (GObject *object)
+{
+  ThunarVfsVolumeManager *manager = THUNAR_VFS_VOLUME_MANAGER (object);
+  ThunarVfsVolume        *volume;
+
+  /* drop all managed volumes */
+  while (manager->volumes != NULL)
+    {
+      /* grab the first volume */
+      volume = THUNAR_VFS_VOLUME (manager->volumes->data);
+
+      /* verify that we're the only one keeping a reference on it */
+      if (G_UNLIKELY (G_OBJECT (volume)->ref_count > 1))
+        {
+          g_warning ("Attempt detected to finalize the ThunarVfsVolumeManager, while "
+                     "there are still ThunarVfsVolume instances with a reference count "
+                     "of 2 or more. This usually presents a bug in the application.");
+        }
+
+      /* disconnect from the volume */
+      thunar_vfs_volume_manager_remove (manager, volume);
+    }
+
+  (*G_OBJECT_CLASS (thunar_vfs_volume_manager_parent_class)->finalize) (object);
+}
+
+
+
+static ThunarVfsVolume*
+thunar_vfs_volume_manager_real_get_volume_by_info (ThunarVfsVolumeManager *manager, 
+                                                   const ThunarVfsInfo    *info)
+{
+  ThunarVfsVolume *best_volume = NULL;
+  ThunarVfsPath   *best_path = NULL;
+  ThunarVfsPath   *path;
+  GList           *lp;
+
+  /* otherwise try to find it the hard way */
+  for (lp = manager->volumes; lp != NULL; lp = lp->next)
+    {
+      /* check if the volume is mounted */
+      if (!thunar_vfs_volume_is_mounted (lp->data))
+        continue;
+
+      /* check if the mount point is an ancestor of the info path */
+      path = thunar_vfs_volume_get_mount_point (lp->data);
+      if (path == NULL || (!thunar_vfs_path_equal (info->path, path) && !thunar_vfs_path_is_ancestor (info->path, path)))
+        continue;
+
+      /* possible match, check if better than previous match */
+      if (best_volume == NULL || thunar_vfs_path_equal (path, best_path) || thunar_vfs_path_is_ancestor (path, best_path))
+        {
+          best_volume = lp->data;
+          best_path = path;
+        }
+    }
+
+  return best_volume;
+}
+
+
+
+static void
+thunar_vfs_volume_manager_volume_mounted (ThunarVfsVolumeManager *manager,
+                                          ThunarVfsVolume        *volume)
+{
+  g_return_if_fail (THUNAR_VFS_IS_VOLUME (volume));
+  g_return_if_fail (THUNAR_VFS_IS_VOLUME_MANAGER (manager));
+  g_return_if_fail (g_list_find (manager->volumes, volume) != NULL);
+  g_signal_emit (G_OBJECT (manager), manager_signals[VOLUME_MOUNTED], 0, volume);
+}
+
+
+
+static void
+thunar_vfs_volume_manager_volume_pre_unmount (ThunarVfsVolumeManager *manager,
+                                              ThunarVfsVolume        *volume)
+{
+  g_return_if_fail (THUNAR_VFS_IS_VOLUME (volume));
+  g_return_if_fail (THUNAR_VFS_IS_VOLUME_MANAGER (manager));
+  g_return_if_fail (g_list_find (manager->volumes, volume) != NULL);
+  g_signal_emit (G_OBJECT (manager), manager_signals[VOLUME_PRE_UNMOUNT], 0, volume);
+}
+
+
+
+static void
+thunar_vfs_volume_manager_volume_unmounted (ThunarVfsVolumeManager *manager,
+                                            ThunarVfsVolume        *volume)
+{
+  g_return_if_fail (THUNAR_VFS_IS_VOLUME (volume));
+  g_return_if_fail (THUNAR_VFS_IS_VOLUME_MANAGER (manager));
+  g_return_if_fail (g_list_find (manager->volumes, volume) != NULL);
+  g_signal_emit (G_OBJECT (manager), manager_signals[VOLUME_UNMOUNTED], 0, volume);
+}
+
+
+
+/**
+ * thunar_vfs_volume_manager_get_default:
+ * 
+ * Returns the default, shared #ThunarVfsVolumeManager instance
+ * for this system. This function automatically determines, which
+ * implementation of #ThunarVfsVolumeManager should be used for
+ * the target system and returns an instance of that class, which
+ * is shared among all modules using the volume manager facility.
+ *
+ * Call g_object_unref() on the returned object when you are
+ * done with it.
+ *
+ * Return value: the shared #ThunarVfsVolumeManager instance.
+ **/
+ThunarVfsVolumeManager*
+thunar_vfs_volume_manager_get_default (void)
+{
+  static ThunarVfsVolumeManager *manager = NULL;
+
+  if (G_UNLIKELY (manager == NULL))
+    {
+      manager = g_object_new (THUNAR_VFS_TYPE_VOLUME_MANAGER_IMPL, NULL);
+      g_object_add_weak_pointer (G_OBJECT (manager), (gpointer) &manager);
+    }
+  else
+    {
+      g_object_ref (G_OBJECT (manager));
+    }
+
+  return manager;
+}
+
+
+
+/**
+ * thunar_vfs_volume_manager_get_volume_by_info:
+ * @manager : a #ThunarVfsVolumeManager instance.
+ * @info    : a #ThunarVfsInfo.
+ *
+ * Tries to lookup the #ThunarVfsVolume on which @info is
+ * located. If @manager doesn't know a #ThunarVfsVolume
+ * for @info, %NULL will be returned.
+ *
+ * The returned #ThunarVfsVolume (if any) is owned by
+ * @manager and must not be freed by the caller.
+ *
+ * Return value: the #ThunarVfsVolume, on which @info is
+ *               located or %NULL.
+ **/
+ThunarVfsVolume*
+thunar_vfs_volume_manager_get_volume_by_info (ThunarVfsVolumeManager *manager,
+                                              const ThunarVfsInfo    *info)
+{
+  g_return_val_if_fail (THUNAR_VFS_IS_VOLUME_MANAGER (manager), NULL);
+  g_return_val_if_fail (info != NULL, NULL);
+  return (*THUNAR_VFS_VOLUME_MANAGER_GET_CLASS (manager)->get_volume_by_info) (manager, info);
+}
+
+
+
+/**
+ * thunar_vfs_volume_manager_get_volumes:
+ * @manager : a #ThunarVfsVolumeManager instance.
+ *
+ * Returns all #ThunarVfsVolume<!---->s currently known for
+ * @manager. The returned list is owned by @manager and should
+ * therefore considered constant in the caller.
+ *
+ * Return value: the list of volumes known for @manager.
+ **/
+GList*
+thunar_vfs_volume_manager_get_volumes (ThunarVfsVolumeManager *manager)
+{
+  g_return_val_if_fail (THUNAR_VFS_IS_VOLUME_MANAGER (manager), NULL);
+  return manager->volumes;
+}
+
+
+
+/**
+ * thunar_vfs_volume_manager_add:
+ * @manager : a #ThunarVfsVolumeManager instance.
+ * @volume  : a #ThunarVfsVolume.
+ *
+ * Adds @volume to the list of #ThunarVfsVolume<!---->s managed
+ * by the @manager, and emits the "volumes-added" signal on
+ * @manager using the given @volume.
+ *
+ * It is an error to call this method with a @volume that is
+ * already managed by @manager.
+ *
+ * This method should only be used by #ThunarVfsVolumeManager
+ * implementations.
+ **/
+void
+thunar_vfs_volume_manager_add (ThunarVfsVolumeManager *manager,
+                               ThunarVfsVolume        *volume)
+{
+  GList list;
+
+  g_return_if_fail (THUNAR_VFS_IS_VOLUME (volume));
+  g_return_if_fail (THUNAR_VFS_IS_VOLUME_MANAGER (manager));
+  g_return_if_fail (g_list_find (manager->volumes, volume) == NULL);
+
+  /* add the volume to the list of managed volumes */
+  manager->volumes = g_list_prepend (manager->volumes, volume);
+  g_object_ref (G_OBJECT (volume));
+
+  /* connect the required signals */
+  g_signal_connect_swapped (G_OBJECT (volume), "mounted", G_CALLBACK (thunar_vfs_volume_manager_volume_mounted), manager);
+  g_signal_connect_swapped (G_OBJECT (volume), "pre-unmount", G_CALLBACK (thunar_vfs_volume_manager_volume_pre_unmount), manager);
+  g_signal_connect_swapped (G_OBJECT (volume), "unmounted", G_CALLBACK (thunar_vfs_volume_manager_volume_unmounted), manager);
+
+  /* fake a volume list */
+  list.data = volume;
+  list.next = NULL;
+  list.prev = NULL;
+
+  /* emit "volumes-added" with the faked list */
+  g_signal_emit (G_OBJECT (manager), manager_signals[VOLUMES_ADDED], 0, &list);
+}
+
+
+
+/**
+ * thunar_vfs_volume_manager_remove:
+ * @manager : a #ThunarVfsVolumeManager instance.
+ * @volume  : a #ThunarVfsVolume.
+ *
+ * Removes @volume from the list of #ThunarVfsVolume<!---->s managed
+ * by the @manager, and emits the "volumes-removed" signal on
+ * @manager using the given @volume.
+ *
+ * It is an error to call this method with @volume that is not
+ * currently managed by @manager.
+ *
+ * This method should only be used by #ThunarVfsVolumeManager
+ * implementations.
+ **/
+void
+thunar_vfs_volume_manager_remove (ThunarVfsVolumeManager *manager,
+                                  ThunarVfsVolume        *volume)
+{
+  GList list;
+
+  g_return_if_fail (THUNAR_VFS_IS_VOLUME (volume));
+  g_return_if_fail (THUNAR_VFS_IS_VOLUME_MANAGER (manager));
+  g_return_if_fail (g_list_find (manager->volumes, volume) != NULL);
+
+  /* remove the volume from our list */
+  manager->volumes = g_list_remove (manager->volumes, volume);
+
+  /* disconnect our signal handlers */
+  g_signal_handlers_disconnect_by_func (G_OBJECT (volume), thunar_vfs_volume_manager_volume_mounted, manager);
+  g_signal_handlers_disconnect_by_func (G_OBJECT (volume), thunar_vfs_volume_manager_volume_pre_unmount, manager);
+  g_signal_handlers_disconnect_by_func (G_OBJECT (volume), thunar_vfs_volume_manager_volume_unmounted, manager);
+
+  /* fake a volume list */
+  list.data = volume;
+  list.next = NULL;
+  list.prev = NULL;
+
+  /* emit "volumes-removed" with the faked list */
+  g_signal_emit (G_OBJECT (manager), manager_signals[VOLUMES_REMOVED], 0, &list);
+
+  /* drop our reference on the volume */
+  g_object_unref (G_OBJECT (volume));
+}
+
+
+
+#define __THUNAR_VFS_VOLUME_MANAGER_C__
+#include <thunar-vfs/thunar-vfs-aliasdef.c>
diff --git a/thunar-vfs/thunar-vfs-volume-none.c b/thunar-vfs/thunar-vfs-volume-none.c
index be9d0cc78..fdc314d24 100644
--- a/thunar-vfs/thunar-vfs-volume-none.c
+++ b/thunar-vfs/thunar-vfs-volume-none.c
@@ -23,76 +23,51 @@
 #endif
 
 #include <thunar-vfs/thunar-vfs-volume-none.h>
+#include <thunar-vfs/thunar-vfs-volume-private.h>
 #include <thunar-vfs/thunar-vfs-alias.h>
 
 
 
-static void             thunar_vfs_volume_manager_none_class_init         (ThunarVfsVolumeManagerNoneClass *klass);
-static void             thunar_vfs_volume_manager_none_manager_init       (ThunarVfsVolumeManagerIface     *iface);
-static void             thunar_vfs_volume_manager_none_init               (ThunarVfsVolumeManagerNone      *manager_none);
-static ThunarVfsVolume *thunar_vfs_volume_manager_none_get_volume_by_info (ThunarVfsVolumeManager          *manager,
-                                                                           const ThunarVfsInfo             *info);
-static GList           *thunar_vfs_volume_manager_none_get_volumes        (ThunarVfsVolumeManager          *manager);
-
-
-
 struct _ThunarVfsVolumeManagerNoneClass
 {
-  GObjectClass __parent__;
+  ThunarVfsVolumeManagerClass __parent__;
 };
 
 struct _ThunarVfsVolumeManagerNone
 {
-  GObject __parent__;
+  ThunarVfsVolumeClass __parent__;
 };
 
 
 
-G_DEFINE_TYPE_WITH_CODE (ThunarVfsVolumeManagerNone,
-                         thunar_vfs_volume_manager_none,
-                         G_TYPE_OBJECT,
-                         G_IMPLEMENT_INTERFACE (THUNAR_VFS_TYPE_VOLUME_MANAGER,
-                                                thunar_vfs_volume_manager_none_manager_init));
-
-
-static void
-thunar_vfs_volume_manager_none_class_init (ThunarVfsVolumeManagerNoneClass *klass)
-{
-}
-
-
-
-static void
-thunar_vfs_volume_manager_none_manager_init (ThunarVfsVolumeManagerIface *iface)
-{
-  iface->get_volume_by_info = thunar_vfs_volume_manager_none_get_volume_by_info;
-  iface->get_volumes = thunar_vfs_volume_manager_none_get_volumes;
-}
-
-
-
-static void
-thunar_vfs_volume_manager_none_init (ThunarVfsVolumeManagerNone *manager_none)
-{
-}
-
-
-
-static ThunarVfsVolume*
-thunar_vfs_volume_manager_none_get_volume_by_info (ThunarVfsVolumeManager *manager,
-                                                   const ThunarVfsInfo    *info)
+GType
+thunar_vfs_volume_manager_none_get_type (void)
 {
-  return NULL;
+  static GType type = G_TYPE_INVALID;
+
+  if (G_UNLIKELY (type == G_TYPE_INVALID))
+    {
+      static const GTypeInfo info =
+      {
+        sizeof (ThunarVfsVolumeManagerNoneClass),
+        NULL,
+        NULL,
+        NULL,
+        NULL,
+        NULL,
+        sizeof (ThunarVfsVolumeManagerNone),
+        0,
+        NULL,
+        NULL,
+      };
+
+      type = g_type_register_static (THUNAR_VFS_TYPE_VOLUME_MANAGER, I_("ThunarVfsVolumeManagerNone"), &info, 0);
+    }
+
+  return type;
 }
 
 
 
-static GList*
-thunar_vfs_volume_manager_none_get_volumes (ThunarVfsVolumeManager *manager)
-{
-  return NULL;
-}
-
-
-
-
+#define __THUNAR_VFS_VOLUME_NONE_C__
+#include <thunar-vfs/thunar-vfs-aliasdef.c>
diff --git a/thunar-vfs/thunar-vfs-volume-private.h b/thunar-vfs/thunar-vfs-volume-private.h
new file mode 100644
index 000000000..bf7933c6a
--- /dev/null
+++ b/thunar-vfs/thunar-vfs-volume-private.h
@@ -0,0 +1,111 @@
+/* $Id$ */
+/*-
+ * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __THUNAR_VFS_VOLUME_PRIVATE_H__
+#define __THUNAR_VFS_VOLUME_PRIVATE_H__
+
+#include <thunar-vfs/thunar-vfs-volume.h>
+
+G_BEGIN_DECLS;
+
+struct _ThunarVfsVolumeClass
+{
+  /*< private >*/
+  GObjectClass __parent__;
+
+  /*< public >*/
+
+  /* methods */
+  ThunarVfsVolumeKind   (*get_kind)         (ThunarVfsVolume   *volume);
+  const gchar          *(*get_name)         (ThunarVfsVolume   *volume);
+  ThunarVfsVolumeStatus (*get_status)       (ThunarVfsVolume   *volume);
+  ThunarVfsPath        *(*get_mount_point)  (ThunarVfsVolume   *volume);
+  const gchar          *(*lookup_icon_name) (ThunarVfsVolume   *volume,
+                                             GtkIconTheme      *icon_theme);
+
+  gboolean              (*eject)            (ThunarVfsVolume   *volume,
+                                             GtkWidget         *window,
+                                             GError           **error);
+  gboolean              (*mount)            (ThunarVfsVolume   *volume,
+                                             GtkWidget         *window,
+                                             GError           **error);
+  gboolean              (*unmount)          (ThunarVfsVolume   *volume,
+                                             GtkWidget         *window,
+                                             GError           **error);
+
+  /* signals */
+  void                  (*changed)          (ThunarVfsVolume   *volume);
+  void                  (*mounted)          (ThunarVfsVolume   *volume);
+  void                  (*pre_unmount)      (ThunarVfsVolume   *volume);
+  void                  (*unmounted)        (ThunarVfsVolume   *volume);
+};
+
+struct _ThunarVfsVolume
+{
+  /*< private >*/
+  GObject __parent__;
+};
+
+void thunar_vfs_volume_changed (ThunarVfsVolume *volume) G_GNUC_INTERNAL;
+
+
+struct _ThunarVfsVolumeManagerClass
+{
+  /*< private >*/
+  GObjectClass __parent__;
+
+  /*< public >*/
+
+  /* methods */
+  ThunarVfsVolume *(*get_volume_by_info)  (ThunarVfsVolumeManager *manager,
+                                           const ThunarVfsInfo    *info);
+
+  /* signals */
+  void             (*volumes_added)       (ThunarVfsVolumeManager *manager,
+                                           GList                  *volumes);
+  void             (*volumes_removed)     (ThunarVfsVolumeManager *manager,
+                                           GList                  *volumes);
+  void             (*volume_mounted)      (ThunarVfsVolumeManager *manager,
+                                           ThunarVfsVolume        *volume);
+  void             (*volume_pre_unmount)  (ThunarVfsVolumeManager *manager,
+                                           ThunarVfsVolume        *volume);
+  void             (*volume_unmounted)    (ThunarVfsVolumeManager *manager,
+                                           ThunarVfsVolume        *volume);
+};
+
+struct _ThunarVfsVolumeManager
+{
+  /*< private >*/
+  GObject __parent__;
+
+  /*< public >*/
+
+  /* the list of available volumes */
+  GList  *volumes;
+};
+
+void thunar_vfs_volume_manager_add    (ThunarVfsVolumeManager *manager,
+                                       ThunarVfsVolume        *volume) G_GNUC_INTERNAL;
+void thunar_vfs_volume_manager_remove (ThunarVfsVolumeManager *manager,
+                                       ThunarVfsVolume        *volume) G_GNUC_INTERNAL;
+
+G_END_DECLS;
+
+#endif /* !__THUNAR_VFS_VOLUME_PRIVATE_H__ */
diff --git a/thunar-vfs/thunar-vfs-volume.c b/thunar-vfs/thunar-vfs-volume.c
index 9a4bfb5ca..51a54e02d 100644
--- a/thunar-vfs/thunar-vfs-volume.c
+++ b/thunar-vfs/thunar-vfs-volume.c
@@ -22,44 +22,29 @@
 #include <config.h>
 #endif
 
-#include <exo/exo.h>
-
 #include <thunar-vfs/thunar-vfs-enum-types.h>
-#include <thunar-vfs/thunar-vfs-volume-freebsd.h>
-#include <thunar-vfs/thunar-vfs-volume-hal.h>
-#include <thunar-vfs/thunar-vfs-volume-none.h>
-#include <thunar-vfs/thunar-vfs-volume.h>
+#include <thunar-vfs/thunar-vfs-volume-private.h>
 #include <thunar-vfs/thunar-vfs-alias.h>
 
 
 
-/* determine the default thunar vfs volume manager type */
-#if defined(THUNAR_VFS_VOLUME_IMPL_FREEBSD)
-#define THUNAR_VFS_TYPE_VOLUME_MANAGER_IMPL THUNAR_VFS_TYPE_VOLUME_MANAGER_FREEBSD
-#elif defined(THUNAR_VFS_VOLUME_IMPL_HAL)
-#define THUNAR_VFS_TYPE_VOLUME_MANAGER_IMPL THUNAR_VFS_TYPE_VOLUME_MANAGER_HAL
-#elif defined(THUNAR_VFS_VOLUME_IMPL_NONE)
-#define THUNAR_VFS_TYPE_VOLUME_MANAGER_IMPL THUNAR_VFS_TYPE_VOLUME_MANAGER_NONE
-#else
-#error "Add your volume manager implemenation here!"
-#endif
-
-
-
 /* Signal identifiers */
 enum
 {
-  THUNAR_VFS_VOLUME_CHANGED,
-  THUNAR_VFS_VOLUME_LAST_SIGNAL,
+  CHANGED,
+  MOUNTED,
+  PRE_UNMOUNT,
+  UNMOUNTED,
+  LAST_SIGNAL,
 };
 
 
 
-static void thunar_vfs_volume_base_init (gpointer klass);
+static void thunar_vfs_volume_class_init (ThunarVfsVolumeClass *klass);
 
 
 
-static guint volume_signals[THUNAR_VFS_VOLUME_LAST_SIGNAL];
+static guint volume_signals[LAST_SIGNAL];
 
 
 
@@ -72,20 +57,19 @@ thunar_vfs_volume_get_type (void)
     {
       static const GTypeInfo info =
       {
-        sizeof (ThunarVfsVolumeIface),
-        (GBaseInitFunc) thunar_vfs_volume_base_init,
+        sizeof (ThunarVfsVolumeClass),
         NULL,
         NULL,
+        (GClassInitFunc) thunar_vfs_volume_class_init,
         NULL,
         NULL,
-        0,
+        sizeof (ThunarVfsVolume),
         0,
         NULL,
         NULL,
       };
 
-      type = g_type_register_static (G_TYPE_INTERFACE, I_("ThunarVfsVolume"), &info, 0);
-      g_type_interface_add_prerequisite (type, G_TYPE_OBJECT);
+      type = g_type_register_static (G_TYPE_OBJECT, I_("ThunarVfsVolume"), &info, G_TYPE_FLAG_ABSTRACT);
     }
 
   return type;
@@ -94,29 +78,70 @@ thunar_vfs_volume_get_type (void)
 
 
 static void
-thunar_vfs_volume_base_init (gpointer klass)
+thunar_vfs_volume_class_init (ThunarVfsVolumeClass *klass)
 {
-  static gboolean initialized = FALSE;
-
-  if (G_UNLIKELY (!initialized))
-    {
-      /**
-       * ThunarVfsVolume::changed:
-       * @volume : the #ThunarVfsVolume instance.
-       *
-       * Emitted whenever the state of @volume changed.
-       **/
-      volume_signals[THUNAR_VFS_VOLUME_CHANGED] =
-        g_signal_new (I_("changed"),
-                      G_TYPE_FROM_INTERFACE (klass),
-                      G_SIGNAL_RUN_LAST,
-                      G_STRUCT_OFFSET (ThunarVfsVolumeIface, changed),
-                      NULL, NULL,
-                      g_cclosure_marshal_VOID__VOID,
-                      G_TYPE_NONE, 0);
-
-      initialized = TRUE;
-    }
+  /**
+   * ThunarVfsVolume::changed:
+   * @volume : the #ThunarVfsVolume instance.
+   *
+   * Emitted whenever the state of @volume changed.
+   **/
+  volume_signals[CHANGED] =
+    g_signal_new (I_("changed"),
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (ThunarVfsVolumeClass, changed),
+                  NULL, NULL,
+                  g_cclosure_marshal_VOID__VOID,
+                  G_TYPE_NONE, 0);
+
+  /**
+   * ThunarVfsVolume::mounted:
+   * @volume : the #ThunarVfsVolume instance.
+   *
+   * Emitted by @volume after a successfull mount
+   * operation.
+   **/
+  volume_signals[MOUNTED] =
+    g_signal_new (I_("mounted"),
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (ThunarVfsVolumeClass, mounted),
+                  NULL, NULL,
+                  g_cclosure_marshal_VOID__VOID,
+                  G_TYPE_NONE, 0);
+
+  /**
+   * ThunarVfsVolume::pre-unmount:
+   * @volume : the #ThunarVfsVolume instance.
+   *
+   * Emitted by @volume right before an attempt
+   * is made to unmount the @volume.
+   **/
+  volume_signals[PRE_UNMOUNT] =
+    g_signal_new (I_("pre-unmount"),
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (ThunarVfsVolumeClass, pre_unmount),
+                  NULL, NULL,
+                  g_cclosure_marshal_VOID__VOID,
+                  G_TYPE_NONE, 0);
+
+  /**
+   * ThunarVfsVolume::unmounted:
+   * @volume : the #ThunarVfsVolume instance.
+   *
+   * Emitted by @volume right after the @volume
+   * was successfully unmounted.
+   **/
+  volume_signals[UNMOUNTED] =
+    g_signal_new (I_("unmounted"),
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (ThunarVfsVolumeClass, unmounted),
+                  NULL, NULL,
+                  g_cclosure_marshal_VOID__VOID,
+                  G_TYPE_NONE, 0);
 }
 
 
@@ -133,7 +158,7 @@ ThunarVfsVolumeKind
 thunar_vfs_volume_get_kind (ThunarVfsVolume *volume)
 {
   g_return_val_if_fail (THUNAR_VFS_IS_VOLUME (volume), THUNAR_VFS_VOLUME_KIND_UNKNOWN);
-  return (*THUNAR_VFS_VOLUME_GET_IFACE (volume)->get_kind) (volume);
+  return (*THUNAR_VFS_VOLUME_GET_CLASS (volume)->get_kind) (volume);
 }
 
 
@@ -152,7 +177,7 @@ const gchar*
 thunar_vfs_volume_get_name (ThunarVfsVolume *volume)
 {
   g_return_val_if_fail (THUNAR_VFS_IS_VOLUME (volume), NULL);
-  return (*THUNAR_VFS_VOLUME_GET_IFACE (volume)->get_name) (volume);
+  return (*THUNAR_VFS_VOLUME_GET_CLASS (volume)->get_name) (volume);
 }
 
 
@@ -171,7 +196,7 @@ ThunarVfsVolumeStatus
 thunar_vfs_volume_get_status (ThunarVfsVolume *volume)
 {
   g_return_val_if_fail (THUNAR_VFS_IS_VOLUME (volume), 0);
-  return (*THUNAR_VFS_VOLUME_GET_IFACE (volume)->get_status) (volume);
+  return (*THUNAR_VFS_VOLUME_GET_CLASS (volume)->get_status) (volume);
 }
 
 
@@ -195,7 +220,7 @@ ThunarVfsPath*
 thunar_vfs_volume_get_mount_point (ThunarVfsVolume *volume)
 {
   g_return_val_if_fail (THUNAR_VFS_IS_VOLUME (volume), NULL);
-  return (*THUNAR_VFS_VOLUME_GET_IFACE (volume)->get_mount_point) (volume);
+  return (*THUNAR_VFS_VOLUME_GET_CLASS (volume)->get_mount_point) (volume);
 }
 
 
@@ -237,7 +262,7 @@ gboolean
 thunar_vfs_volume_is_mounted (ThunarVfsVolume *volume)
 {
   g_return_val_if_fail (THUNAR_VFS_IS_VOLUME (volume), FALSE);
-  return (*THUNAR_VFS_VOLUME_GET_IFACE (volume)->get_status) (volume) & THUNAR_VFS_VOLUME_STATUS_MOUNTED;
+  return (*THUNAR_VFS_VOLUME_GET_CLASS (volume)->get_status) (volume) & THUNAR_VFS_VOLUME_STATUS_MOUNTED;
 }
 
 
@@ -256,7 +281,7 @@ gboolean
 thunar_vfs_volume_is_present (ThunarVfsVolume *volume)
 {
   g_return_val_if_fail (THUNAR_VFS_IS_VOLUME (volume), FALSE);
-  return (*THUNAR_VFS_VOLUME_GET_IFACE (volume)->get_status) (volume) & THUNAR_VFS_VOLUME_STATUS_PRESENT;
+  return (*THUNAR_VFS_VOLUME_GET_CLASS (volume)->get_status) (volume) & THUNAR_VFS_VOLUME_STATUS_PRESENT;
 }
 
 
@@ -340,7 +365,7 @@ const gchar*
 thunar_vfs_volume_lookup_icon_name (ThunarVfsVolume *volume,
                                     GtkIconTheme    *icon_theme)
 {
-  ThunarVfsVolumeIface *iface;
+  ThunarVfsVolumeClass *klass;
   ThunarVfsVolumeKind   kind;
   const gchar          *icon_name;
 
@@ -348,10 +373,10 @@ thunar_vfs_volume_lookup_icon_name (ThunarVfsVolume *volume,
   g_return_val_if_fail (GTK_IS_ICON_THEME (icon_theme), NULL);
 
   /* allow the implementing class to provide a custom icon */
-  iface = THUNAR_VFS_VOLUME_GET_IFACE (volume);
-  if (iface->lookup_icon_name != NULL)
+  klass = THUNAR_VFS_VOLUME_GET_CLASS (volume);
+  if (klass->lookup_icon_name != NULL)
     {
-      icon_name = (*iface->lookup_icon_name) (volume, icon_theme);
+      icon_name = (*klass->lookup_icon_name) (volume, icon_theme);
       if (G_LIKELY (icon_name != NULL))
         return icon_name;
     }
@@ -469,6 +494,9 @@ thunar_vfs_volume_eject (ThunarVfsVolume *volume,
   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
   g_return_val_if_fail (window == NULL || GTK_IS_WINDOW (window), FALSE);
 
+  /* we're about to unmount (and eject) the volume */
+  g_signal_emit (G_OBJECT (volume), volume_signals[PRE_UNMOUNT], 0);
+
   /* setup a watch cursor on the window */
   if (window != NULL && GTK_WIDGET_REALIZED (window))
     {
@@ -482,12 +510,16 @@ thunar_vfs_volume_eject (ThunarVfsVolume *volume,
     }
 
   /* try to mount the volume */
-  result = (*THUNAR_VFS_VOLUME_GET_IFACE (volume)->eject) (volume, window, error);
+  result = (*THUNAR_VFS_VOLUME_GET_CLASS (volume)->eject) (volume, window, error);
 
   /* reset the cursor */
   if (window != NULL && GTK_WIDGET_REALIZED (window))
     gdk_window_set_cursor (window->window, NULL);
 
+  /* check if we unmounted successfully */
+  if (G_LIKELY (result))
+    g_signal_emit (G_OBJECT (volume), volume_signals[UNMOUNTED], 0);
+
   return result;
 }
 
@@ -540,12 +572,16 @@ thunar_vfs_volume_mount (ThunarVfsVolume *volume,
     }
 
   /* try to mount the volume */
-  result = (*THUNAR_VFS_VOLUME_GET_IFACE (volume)->mount) (volume, window, error);
+  result = (*THUNAR_VFS_VOLUME_GET_CLASS (volume)->mount) (volume, window, error);
 
   /* reset the cursor */
   if (window != NULL && GTK_WIDGET_REALIZED (window))
     gdk_window_set_cursor (window->window, NULL);
 
+  /* check if we successfully mounted the volume */
+  if (G_LIKELY (result))
+    g_signal_emit (G_OBJECT (volume), volume_signals[MOUNTED], 0);
+
   return result;
 }
 
@@ -585,6 +621,9 @@ thunar_vfs_volume_unmount (ThunarVfsVolume *volume,
   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
   g_return_val_if_fail (window == NULL || GTK_IS_WINDOW (window), FALSE);
 
+  /* we're about to unmount the volume */
+  g_signal_emit (G_OBJECT (volume), volume_signals[PRE_UNMOUNT], 0);
+
   /* setup a watch cursor on the window */
   if (window != NULL && GTK_WIDGET_REALIZED (window))
     {
@@ -598,12 +637,16 @@ thunar_vfs_volume_unmount (ThunarVfsVolume *volume,
     }
 
   /* try to mount the volume */
-  result = (*THUNAR_VFS_VOLUME_GET_IFACE (volume)->unmount) (volume, window, error);
+  result = (*THUNAR_VFS_VOLUME_GET_CLASS (volume)->unmount) (volume, window, error);
 
   /* reset the cursor */
   if (window != NULL && GTK_WIDGET_REALIZED (window))
     gdk_window_set_cursor (window->window, NULL);
 
+  /* check if we unmounted successfully */
+  if (G_LIKELY (result))
+    g_signal_emit (G_OBJECT (volume), volume_signals[UNMOUNTED], 0);
+
   return result;
 }
 
@@ -621,237 +664,11 @@ void
 thunar_vfs_volume_changed (ThunarVfsVolume *volume)
 {
   g_return_if_fail (THUNAR_VFS_IS_VOLUME (volume));
-  g_signal_emit (G_OBJECT (volume), volume_signals[THUNAR_VFS_VOLUME_CHANGED], 0);
-}
-
-
-
-
-enum
-{
-  THUNAR_VFS_VOLUME_MANAGER_VOLUMES_ADDED,
-  THUNAR_VFS_VOLUME_MANAGER_VOLUMES_REMOVED,
-  THUNAR_VFS_VOLUME_MANAGER_LAST_SIGNAL,
-};
-
-
-
-static void thunar_vfs_volume_manager_base_init (gpointer klass);
-
-
-
-static guint manager_signals[THUNAR_VFS_VOLUME_MANAGER_LAST_SIGNAL];
-
-
-
-GType
-thunar_vfs_volume_manager_get_type (void)
-{
-  static GType type = G_TYPE_INVALID;
-
-  if (G_UNLIKELY (type == G_TYPE_INVALID))
-    {
-      static const GTypeInfo info =
-      {
-        sizeof (ThunarVfsVolumeManagerIface),
-        (GBaseInitFunc) thunar_vfs_volume_manager_base_init,
-        NULL,
-        NULL,
-        NULL,
-        NULL,
-        0,
-        0,
-        NULL,
-      };
-
-      type = g_type_register_static (G_TYPE_INTERFACE,
-                                     "ThunarVfsVolumeManager",
-                                     &info, 0);
-
-      g_type_interface_add_prerequisite (type, G_TYPE_OBJECT);
-    }
-
-  return type;
-}
-
-
-
-static void
-thunar_vfs_volume_manager_base_init (gpointer klass)
-{
-  static gboolean initialized = FALSE;
-
-  if (G_UNLIKELY (!initialized))
-    {
-      /**
-       * ThunarVfsVolumeManager::volumes-added:
-       * @manager : a #ThunarVfsVolumeManager instance.
-       * @volumes : a list of #ThunarVfsVolume<!---->s.
-       *
-       * Invoked by the @manager whenever new volumes have been
-       * attached to the system or the administrator changes the
-       * /etc/fstab file, or some other condition, depending
-       * on the manager implementation.
-       *
-       * Note that the implementation should not invoke this
-       * method when a volume is mounted, as that's a completely
-       * different condition!
-       **/
-      manager_signals[THUNAR_VFS_VOLUME_MANAGER_VOLUMES_ADDED] =
-        g_signal_new (I_("volumes-added"),
-                      G_TYPE_FROM_INTERFACE (klass),
-                      G_SIGNAL_RUN_LAST,
-                      G_STRUCT_OFFSET (ThunarVfsVolumeManagerIface, volumes_added),
-                      NULL, NULL,
-                      g_cclosure_marshal_VOID__POINTER,
-                      G_TYPE_NONE, 1, G_TYPE_POINTER);
-
-      /**
-       * ThunarVfsVolumeManager::volumes-removed:
-       * @manager : a #ThunarVfsVolume instance.
-       * @volumes : a list of #ThunarVfsVolume<!---->s.
-       *
-       * Invoked whenever the @manager notices that @volumes have
-       * been detached from the system.
-       **/
-      manager_signals[THUNAR_VFS_VOLUME_MANAGER_VOLUMES_REMOVED] =
-        g_signal_new (I_("volumes-removed"),
-                      G_TYPE_FROM_INTERFACE (klass),
-                      G_SIGNAL_RUN_LAST,
-                      G_STRUCT_OFFSET (ThunarVfsVolumeManagerIface, volumes_removed),
-                      NULL, NULL,
-                      g_cclosure_marshal_VOID__POINTER,
-                      G_TYPE_NONE, 1, G_TYPE_POINTER);
-
-      initialized = TRUE;
-    }
-}
-
-
-
-/**
- * thunar_vfs_volume_manager_get_default:
- * 
- * Returns the default, shared #ThunarVfsVolumeManager instance
- * for this system. This function automatically determines, which
- * implementation of #ThunarVfsVolumeManager should be used for
- * the target system and returns an instance of that class, which
- * is shared among all modules using the volume manager facility.
- *
- * Call g_object_unref() on the returned object when you are
- * done with it.
- *
- * Return value: the shared #ThunarVfsVolumeManager instance.
- **/
-ThunarVfsVolumeManager*
-thunar_vfs_volume_manager_get_default (void)
-{
-  extern GType _thunar_vfs_volume_manager_impl_get_type (void);
-  static ThunarVfsVolumeManager *manager = NULL;
-
-  if (G_UNLIKELY (manager == NULL))
-    {
-      manager = g_object_new (THUNAR_VFS_TYPE_VOLUME_MANAGER_IMPL, NULL);
-      g_object_add_weak_pointer (G_OBJECT (manager), (gpointer) &manager);
-    }
-  else
-    {
-      g_object_ref (G_OBJECT (manager));
-    }
-
-  return manager;
-}
-
-
-
-/**
- * thunar_vfs_volume_manager_get_volume_by_info:
- * @manager : a #ThunarVfsVolumeManager instance.
- * @info    : a #ThunarVfsInfo.
- *
- * Tries to lookup the #ThunarVfsVolume on which @info is
- * located. If @manager doesn't know a #ThunarVfsVolume
- * for @info, %NULL will be returned.
- *
- * The returned #ThunarVfsVolume (if any) is owned by
- * @manager and must not be freed by the caller.
- *
- * Return value: the #ThunarVfsVolume, on which @info is
- *               located or %NULL.
- **/
-ThunarVfsVolume*
-thunar_vfs_volume_manager_get_volume_by_info (ThunarVfsVolumeManager *manager,
-                                              const ThunarVfsInfo    *info)
-{
-  g_return_val_if_fail (THUNAR_VFS_IS_VOLUME_MANAGER (manager), NULL);
-  g_return_val_if_fail (info != NULL, NULL);
-  return (*THUNAR_VFS_VOLUME_MANAGER_GET_IFACE (manager)->get_volume_by_info) (manager, info);
+  g_signal_emit (G_OBJECT (volume), volume_signals[CHANGED], 0);
 }
 
 
 
-/**
- * thunar_vfs_volume_manager_get_volumes:
- * @manager : a #ThunarVfsVolumeManager instance.
- *
- * Returns all #ThunarVfsVolume<!---->s currently known for
- * @manager. The returned list is owned by @manager and should
- * therefore considered constant in the caller.
- *
- * Return value: the list of volumes known for @manager.
- **/
-GList*
-thunar_vfs_volume_manager_get_volumes (ThunarVfsVolumeManager *manager)
-{
-  g_return_val_if_fail (THUNAR_VFS_IS_VOLUME_MANAGER (manager), NULL);
-  return (*THUNAR_VFS_VOLUME_MANAGER_GET_IFACE (manager)->get_volumes) (manager);
-}
-
-
-
-/**
- * thunar_vfs_volume_manager_volumes_added:
- * @manager : a #ThunarVfsVolumeManager instance.
- * @volumes : a list of #ThunarVfsVolume<!---->s.
- *
- * Emits the "volumes-added" signal on @manager using the
- * given @volumes.
- *
- * This method should only be used by classes implementing
- * the #ThunarVfsVolumeManager interface.
- **/
-void
-thunar_vfs_volume_manager_volumes_added (ThunarVfsVolumeManager *manager,
-                                         GList                  *volumes)
-{
-  g_return_if_fail (THUNAR_VFS_IS_VOLUME_MANAGER (manager));
-  g_return_if_fail (g_list_length (volumes) > 0);
-  g_signal_emit (G_OBJECT (manager), manager_signals[THUNAR_VFS_VOLUME_MANAGER_VOLUMES_ADDED], 0, volumes);
-}
-
-
-
-/**
- * thunar_vfs_volume_manager_volumes_removed:
- * @manager : a #ThunarVfsVolumeManager instance.
- * @volumes : a list of #ThunarVfsVolume<!---->s.
- *
- * Emits the "volumes-removed" signal on @manager using
- * the given @volumes.
- *
- * This method should only be used by classes implementing
- * the #ThunarVfsVolumeManager interface.
- **/
-void
-thunar_vfs_volume_manager_volumes_removed (ThunarVfsVolumeManager *manager,
-                                           GList                  *volumes)
-{
-  g_return_if_fail (THUNAR_VFS_IS_VOLUME_MANAGER (manager));
-  g_return_if_fail (g_list_length (volumes) > 0);
-  g_signal_emit (G_OBJECT (manager), manager_signals[THUNAR_VFS_VOLUME_MANAGER_VOLUMES_REMOVED], 0, volumes);
-}
-
-
 
 #define __THUNAR_VFS_VOLUME_C__
 #include <thunar-vfs/thunar-vfs-aliasdef.c>
diff --git a/thunar-vfs/thunar-vfs-volume.h b/thunar-vfs/thunar-vfs-volume.h
index 8d7b02563..5f6879165 100644
--- a/thunar-vfs/thunar-vfs-volume.h
+++ b/thunar-vfs/thunar-vfs-volume.h
@@ -27,13 +27,15 @@
 
 G_BEGIN_DECLS;
 
-typedef struct _ThunarVfsVolumeIface ThunarVfsVolumeIface;
+typedef struct _ThunarVfsVolumeClass ThunarVfsVolumeClass;
 typedef struct _ThunarVfsVolume      ThunarVfsVolume;
 
 #define THUNAR_VFS_TYPE_VOLUME            (thunar_vfs_volume_get_type ())
 #define THUNAR_VFS_VOLUME(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_VFS_TYPE_VOLUME, ThunarVfsVolume))
+#define THUNAR_VFS_VOLUME_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), THUNAR_VFS_TYPE_VOLUME, ThunarVfsVolumeClass))
 #define THUNAR_VFS_IS_VOLUME(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THUNAR_VFS_TYPE_VOLUME))
-#define THUNAR_VFS_VOLUME_GET_IFACE(obj)  (G_TYPE_INSTANCE_GET_INTERFACE ((obj), THUNAR_VFS_TYPE_VOLUME, ThunarVfsVolumeIface))
+#define THUNAR_VFS_IS_VOLUME_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), THUNAR_VFS_TYPE_VOLUME))
+#define THUNAR_VFS_VOLUME_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_VFS_TYPE_VOLUME, ThunarVfsVolumeClass))
 
 /**
  * ThunarVfsVolumeKind:
@@ -85,51 +87,6 @@ typedef enum /*< flags >*/
   THUNAR_VFS_VOLUME_STATUS_PRESENT = 1 << 1,
 } ThunarVfsVolumeStatus;
 
-struct _ThunarVfsVolumeIface
-{
-  /*< private >*/
-  GTypeInterface __parent__;
-
-  /*< public >*/
-
-  /* methods */
-  ThunarVfsVolumeKind   (*get_kind)         (ThunarVfsVolume   *volume);
-  const gchar          *(*get_name)         (ThunarVfsVolume   *volume);
-  ThunarVfsVolumeStatus (*get_status)       (ThunarVfsVolume   *volume);
-  ThunarVfsPath        *(*get_mount_point)  (ThunarVfsVolume   *volume);
-  const gchar          *(*lookup_icon_name) (ThunarVfsVolume   *volume,
-                                             GtkIconTheme      *icon_theme);
-
-  gboolean              (*eject)            (ThunarVfsVolume   *volume,
-                                             GtkWidget         *window,
-                                             GError           **error);
-  gboolean              (*mount)            (ThunarVfsVolume   *volume,
-                                             GtkWidget         *window,
-                                             GError           **error);
-  gboolean              (*unmount)          (ThunarVfsVolume   *volume,
-                                             GtkWidget         *window,
-                                             GError           **error);
-
-  /*< private >*/
-  void (*reserved0) (void);
-  void (*reserved1) (void);
-  void (*reserved2) (void);
-  void (*reserved3) (void);
-  void (*reserved4) (void);
-  void (*reserved5) (void);
-
-  /*< public >*/
-
-  /* signals */
-  void (*changed) (ThunarVfsVolume *volume);
-  
-  /*< private >*/
-  void (*reserved6) (void);
-  void (*reserved7) (void);
-  void (*reserved8) (void);
-  void (*reserved9) (void);
-};
-
 GType                 thunar_vfs_volume_get_type          (void) G_GNUC_CONST;
 
 ThunarVfsVolumeKind   thunar_vfs_volume_get_kind          (ThunarVfsVolume   *volume);
@@ -156,51 +113,16 @@ gboolean              thunar_vfs_volume_unmount           (ThunarVfsVolume   *vo
                                                            GtkWidget         *window,
                                                            GError           **error);
 
-void                  thunar_vfs_volume_changed           (ThunarVfsVolume   *volume) G_GNUC_INTERNAL;
-
 
-typedef struct _ThunarVfsVolumeManagerIface ThunarVfsVolumeManagerIface;
+typedef struct _ThunarVfsVolumeManagerClass ThunarVfsVolumeManagerClass;
 typedef struct _ThunarVfsVolumeManager      ThunarVfsVolumeManager;
 
 #define THUNAR_VFS_TYPE_VOLUME_MANAGER            (thunar_vfs_volume_manager_get_type ())
 #define THUNAR_VFS_VOLUME_MANAGER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_VFS_TYPE_VOLUME_MANAGER, ThunarVfsVolumeManager))
+#define THUNAR_VFS_VOLUME_MANAGER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), THUNAR_VFS_TYPE_VOLUME_MANAGER, ThunarVfsVolumeManagerClass))
 #define THUNAR_VFS_IS_VOLUME_MANAGER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THUNAR_VFS_TYPE_VOLUME_MANAGER))
-#define THUNAR_VFS_VOLUME_MANAGER_GET_IFACE(obj)  (G_TYPE_INSTANCE_GET_INTERFACE ((obj), THUNAR_VFS_TYPE_VOLUME_MANAGER, ThunarVfsVolumeManagerIface))
-
-struct _ThunarVfsVolumeManagerIface
-{
-  /*< private >*/
-  GTypeInterface __parent__;
-
-  /*< public >*/
-
-  /* methods */
-  ThunarVfsVolume *(*get_volume_by_info) (ThunarVfsVolumeManager *manager,
-                                          const ThunarVfsInfo    *info);
-  GList           *(*get_volumes)        (ThunarVfsVolumeManager *manager);
-
-  /*< private >*/
-  void (*reserved0) (void);
-  void (*reserved1) (void);
-  void (*reserved2) (void);
-  void (*reserved3) (void);
-  void (*reserved4) (void);
-  void (*reserved5) (void);
-
-  /*< public >*/
-
-  /* signals */
-  void (*volumes_added)   (ThunarVfsVolumeManager *manager,
-                           GList                  *volumes);
-  void (*volumes_removed) (ThunarVfsVolumeManager *manager,
-                           GList                  *volumes);
-
-  /*< private >*/
-  void (*reserved6) (void);
-  void (*reserved7) (void);
-  void (*reserved8) (void);
-  void (*reserved9) (void);
-};
+#define THUNAR_VFS_IS_VOLUME_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), THUNAR_VFS_TYPE_VOLUME_MANAGER))
+#define THUNAR_VFS_VOLUME_MANAGER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_VFS_TYPE_VOLUME_MANAGER, ThunarVfsVolumeManagerClass))
 
 GType                   thunar_vfs_volume_manager_get_type            (void) G_GNUC_CONST;
 
@@ -210,11 +132,6 @@ ThunarVfsVolume        *thunar_vfs_volume_manager_get_volume_by_info  (ThunarVfs
                                                                        const ThunarVfsInfo    *info);
 GList                  *thunar_vfs_volume_manager_get_volumes         (ThunarVfsVolumeManager *manager);
 
-void                    thunar_vfs_volume_manager_volumes_added       (ThunarVfsVolumeManager *manager,
-                                                                       GList                  *volumes) G_GNUC_INTERNAL;
-void                    thunar_vfs_volume_manager_volumes_removed     (ThunarVfsVolumeManager *manager,
-                                                                       GList                  *volumes) G_GNUC_INTERNAL;
-
 G_END_DECLS;
 
 #endif /* !__THUNAR_VFS_VOLUME_H__ */
diff --git a/thunar-vfs/thunar-vfs.symbols b/thunar-vfs/thunar-vfs.symbols
index fd6af31be..bda4a1d3b 100644
--- a/thunar-vfs/thunar-vfs.symbols
+++ b/thunar-vfs/thunar-vfs.symbols
@@ -318,6 +318,8 @@ thunar_vfs_volume_lookup_icon_name
 thunar_vfs_volume_eject
 thunar_vfs_volume_mount
 thunar_vfs_volume_unmount
+#endif
+#if IN_SOURCE(__THUNAR_VFS_VOLUME_MANAGER_C__)
 thunar_vfs_volume_manager_get_type G_GNUC_CONST
 thunar_vfs_volume_manager_get_default
 thunar_vfs_volume_manager_get_volume_by_info
@@ -325,3 +327,4 @@ thunar_vfs_volume_manager_get_volumes
 #endif
 #endif
 
+
diff --git a/thunar/thunar-window.c b/thunar/thunar-window.c
index 41eefa279..a70218c39 100644
--- a/thunar/thunar-window.c
+++ b/thunar/thunar-window.c
@@ -70,93 +70,96 @@ 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 gboolean thunar_window_reload                      (ThunarWindow       *window);
-static gboolean thunar_window_zoom_in                     (ThunarWindow       *window);
-static gboolean thunar_window_zoom_out                    (ThunarWindow       *window);
-static void     thunar_window_realize                     (GtkWidget          *widget);
-static void     thunar_window_unrealize                   (GtkWidget          *widget);
-static gboolean thunar_window_configure_event             (GtkWidget          *widget,
-                                                           GdkEventConfigure  *event);
-static void     thunar_window_merge_custom_preferences    (ThunarWindow       *window);
-static void     thunar_window_install_sidepane            (ThunarWindow       *window,
-                                                           GType               type);
-static void     thunar_window_start_open_location         (ThunarWindow       *window,
-                                                           const gchar        *initial_text);
-static void     thunar_window_action_open_new_window      (GtkAction          *action,
-                                                           ThunarWindow       *window);
-static void     thunar_window_action_close_all_windows    (GtkAction          *action,
-                                                           ThunarWindow       *window);
-static void     thunar_window_action_close                (GtkAction          *action,
-                                                           ThunarWindow       *window);
-static void     thunar_window_action_preferences          (GtkAction          *action,
-                                                           ThunarWindow       *window);
-static void     thunar_window_action_reload               (GtkAction          *action,
-                                                           ThunarWindow       *window);
-static void     thunar_window_action_location_bar_changed (GtkRadioAction     *action,
-                                                           GtkRadioAction     *current,
-                                                           ThunarWindow       *window);
-static void     thunar_window_action_shortcuts_changed    (GtkToggleAction    *action,
-                                                           ThunarWindow       *window);
-static void     thunar_window_action_tree_changed         (GtkToggleAction    *action,
-                                                           ThunarWindow       *window);
-static void     thunar_window_action_statusbar_changed    (GtkToggleAction    *action,
-                                                           ThunarWindow       *window);
-static void     thunar_window_action_zoom_in              (GtkAction          *action,
-                                                           ThunarWindow       *window);
-static void     thunar_window_action_zoom_out             (GtkAction          *action,
-                                                           ThunarWindow       *window);
-static void     thunar_window_action_zoom_reset           (GtkAction          *action,
-                                                           ThunarWindow       *window);
-static void     thunar_window_action_view_changed         (GtkRadioAction     *action,
-                                                           GtkRadioAction     *current,
-                                                           ThunarWindow       *window);
-static void     thunar_window_action_go_up                (GtkAction          *action,
-                                                           ThunarWindow       *window);
-static void     thunar_window_action_open_home            (GtkAction          *action,
-                                                           ThunarWindow       *window);
-static void     thunar_window_action_open_templates       (GtkAction          *action,
-                                                           ThunarWindow       *window);
-static void     thunar_window_action_open_location        (GtkAction          *action,
-                                                           ThunarWindow       *window);
-static void     thunar_window_action_contents             (GtkAction          *action,
-                                                           ThunarWindow       *window);
-static void     thunar_window_action_about                (GtkAction          *action,
-                                                           ThunarWindow       *window);
-static void     thunar_window_action_show_hidden          (GtkToggleAction    *action,
-                                                           ThunarWindow       *window);
-static void     thunar_window_current_directory_changed   (ThunarFile         *current_directory,
-                                                           ThunarWindow       *window);
-static void     thunar_window_connect_proxy               (GtkUIManager       *manager,
-                                                           GtkAction          *action,
-                                                           GtkWidget          *proxy,
-                                                           ThunarWindow       *window);
-static void     thunar_window_disconnect_proxy            (GtkUIManager       *manager,
-                                                           GtkAction          *action,
-                                                           GtkWidget          *proxy,
-                                                           ThunarWindow       *window);
-static void     thunar_window_menu_item_selected          (GtkWidget          *menu_item,
-                                                           ThunarWindow       *window);
-static void     thunar_window_menu_item_deselected        (GtkWidget          *menu_item,
-                                                           ThunarWindow       *window);
-static void     thunar_window_notify_loading              (ThunarView         *view,
-                                                           GParamSpec         *pspec,
-                                                           ThunarWindow       *window);
-static gboolean thunar_window_merge_idle                  (gpointer            user_data);
-static void     thunar_window_merge_idle_destroy          (gpointer            user_data);
-static gboolean thunar_window_save_geometry_timer         (gpointer            user_data);
-static void     thunar_window_save_geometry_timer_destroy (gpointer            user_data);
+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 gboolean thunar_window_reload                      (ThunarWindow           *window);
+static gboolean thunar_window_zoom_in                     (ThunarWindow           *window);
+static gboolean thunar_window_zoom_out                    (ThunarWindow           *window);
+static void     thunar_window_realize                     (GtkWidget              *widget);
+static void     thunar_window_unrealize                   (GtkWidget              *widget);
+static gboolean thunar_window_configure_event             (GtkWidget              *widget,
+                                                           GdkEventConfigure      *event);
+static void     thunar_window_merge_custom_preferences    (ThunarWindow           *window);
+static void     thunar_window_install_sidepane            (ThunarWindow           *window,
+                                                           GType                   type);
+static void     thunar_window_start_open_location         (ThunarWindow           *window,
+                                                           const gchar            *initial_text);
+static void     thunar_window_action_open_new_window      (GtkAction              *action,
+                                                           ThunarWindow           *window);
+static void     thunar_window_action_close_all_windows    (GtkAction              *action,
+                                                           ThunarWindow           *window);
+static void     thunar_window_action_close                (GtkAction              *action,
+                                                           ThunarWindow           *window);
+static void     thunar_window_action_preferences          (GtkAction              *action,
+                                                           ThunarWindow           *window);
+static void     thunar_window_action_reload               (GtkAction              *action,
+                                                           ThunarWindow           *window);
+static void     thunar_window_action_location_bar_changed (GtkRadioAction         *action,
+                                                           GtkRadioAction         *current,
+                                                           ThunarWindow           *window);
+static void     thunar_window_action_shortcuts_changed    (GtkToggleAction        *action,
+                                                           ThunarWindow           *window);
+static void     thunar_window_action_tree_changed         (GtkToggleAction        *action,
+                                                           ThunarWindow           *window);
+static void     thunar_window_action_statusbar_changed    (GtkToggleAction        *action,
+                                                           ThunarWindow           *window);
+static void     thunar_window_action_zoom_in              (GtkAction              *action,
+                                                           ThunarWindow           *window);
+static void     thunar_window_action_zoom_out             (GtkAction              *action,
+                                                           ThunarWindow           *window);
+static void     thunar_window_action_zoom_reset           (GtkAction              *action,
+                                                           ThunarWindow           *window);
+static void     thunar_window_action_view_changed         (GtkRadioAction         *action,
+                                                           GtkRadioAction         *current,
+                                                           ThunarWindow           *window);
+static void     thunar_window_action_go_up                (GtkAction              *action,
+                                                           ThunarWindow           *window);
+static void     thunar_window_action_open_home            (GtkAction              *action,
+                                                           ThunarWindow           *window);
+static void     thunar_window_action_open_templates       (GtkAction              *action,
+                                                           ThunarWindow           *window);
+static void     thunar_window_action_open_location        (GtkAction              *action,
+                                                           ThunarWindow           *window);
+static void     thunar_window_action_contents             (GtkAction              *action,
+                                                           ThunarWindow           *window);
+static void     thunar_window_action_about                (GtkAction              *action,
+                                                           ThunarWindow           *window);
+static void     thunar_window_action_show_hidden          (GtkToggleAction        *action,
+                                                           ThunarWindow           *window);
+static void     thunar_window_current_directory_changed   (ThunarFile             *current_directory,
+                                                           ThunarWindow           *window);
+static void     thunar_window_connect_proxy               (GtkUIManager           *manager,
+                                                           GtkAction              *action,
+                                                           GtkWidget              *proxy,
+                                                           ThunarWindow           *window);
+static void     thunar_window_disconnect_proxy            (GtkUIManager           *manager,
+                                                           GtkAction              *action,
+                                                           GtkWidget              *proxy,
+                                                           ThunarWindow           *window);
+static void     thunar_window_menu_item_selected          (GtkWidget              *menu_item,
+                                                           ThunarWindow           *window);
+static void     thunar_window_menu_item_deselected        (GtkWidget              *menu_item,
+                                                           ThunarWindow           *window);
+static void     thunar_window_notify_loading              (ThunarView             *view,
+                                                           GParamSpec             *pspec,
+                                                           ThunarWindow           *window);
+static void     thunar_window_volume_pre_unmount          (ThunarVfsVolumeManager *volume_manager,
+                                                           ThunarVfsVolume        *volume,
+                                                           ThunarWindow           *window);
+static gboolean thunar_window_merge_idle                  (gpointer                user_data);
+static void     thunar_window_merge_idle_destroy          (gpointer                user_data);
+static gboolean thunar_window_save_geometry_timer         (gpointer                user_data);
+static void     thunar_window_save_geometry_timer_destroy (gpointer                user_data);
 
 
 
@@ -187,6 +190,9 @@ struct _ThunarWindow
   GtkActionGroup         *action_group;
   GtkUIManager           *ui_manager;
 
+  /* to be able to change folder on "volume-pre-unmount" if required */
+  ThunarVfsVolumeManager *volume_manager;
+
   /* closures for the menu_item_selected()/menu_item_deselected() callbacks */
   GClosure               *menu_item_selected_closure;
   GClosure               *menu_item_deselected_closure;
@@ -460,6 +466,10 @@ thunar_window_init (ThunarWindow *window)
   /* allocate the scroll_to_files mapping */
   window->scroll_to_files = g_hash_table_new_full (g_direct_hash, g_direct_equal, g_object_unref, g_object_unref);
 
+  /* connect to the volume manager */
+  window->volume_manager = thunar_vfs_volume_manager_get_default ();
+  g_signal_connect (G_OBJECT (window->volume_manager), "volume-pre-unmount", G_CALLBACK (thunar_window_volume_pre_unmount), window);
+
   /* allocate a closure for the menu_item_selected() callback */
   window->menu_item_selected_closure = g_cclosure_new_object (G_CALLBACK (thunar_window_menu_item_selected), G_OBJECT (window));
   g_closure_ref (window->menu_item_selected_closure);
@@ -692,6 +702,10 @@ thunar_window_finalize (GObject *object)
   g_closure_unref (window->menu_item_deselected_closure);
   g_closure_unref (window->menu_item_selected_closure);
 
+  /* disconnect from the volume manager */
+  g_signal_handlers_disconnect_matched (G_OBJECT (window->volume_manager), G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, window);
+  g_object_unref (G_OBJECT (window->volume_manager));
+
   /* disconnect from the ui manager */
   g_signal_handlers_disconnect_matched (G_OBJECT (window->ui_manager), G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, window);
   g_object_unref (G_OBJECT (window->ui_manager));
@@ -1834,6 +1848,45 @@ thunar_window_notify_loading (ThunarView   *view,
   
 
 
+static void
+thunar_window_volume_pre_unmount (ThunarVfsVolumeManager *volume_manager,
+                                  ThunarVfsVolume        *volume,
+                                  ThunarWindow           *window)
+{
+  ThunarVfsPath *path;
+  ThunarFile    *file;
+  GtkAction     *action;
+
+  g_return_if_fail (THUNAR_VFS_IS_VOLUME_MANAGER (volume_manager));
+  g_return_if_fail (THUNAR_VFS_IS_VOLUME (volume));
+  g_return_if_fail (THUNAR_IS_WINDOW (window));
+
+  /* nothing to do if we don't have a current directory */
+  if (G_UNLIKELY (window->current_directory == NULL))
+    return;
+
+  /* determine the mount point for the volume */
+  path = thunar_vfs_volume_get_mount_point (volume);
+  if (G_UNLIKELY (path == NULL))
+    return;
+
+  /* check if a ThunarFile is known for the mount point */
+  file = thunar_file_cache_lookup (path);
+  if (G_UNLIKELY (file == NULL))
+    return;
+
+  /* check if the file is the current directory or an ancestor of the current directory */
+  if (window->current_directory == file || thunar_file_is_ancestor (window->current_directory, file))
+    {
+      /* change to the home folder */
+      action = gtk_action_group_get_action (window->action_group, "open-home");
+      if (G_LIKELY (action != NULL))
+        gtk_action_activate (action);
+    }
+}
+
+
+
 static gboolean
 thunar_window_merge_idle (gpointer user_data)
 {
-- 
GitLab