gvfs r2119 - in trunk: . client monitor/proxy programs



Author: alexl
Date: Mon Dec  1 13:58:05 2008
New Revision: 2119
URL: http://svn.gnome.org/viewvc/gvfs?rev=2119&view=rev

Log:
2008-12-01  Alexander Larsson  <alexl redhat com>

        * client/gdaemonmount.c:
        * client/gdaemonvolumemonitor.c:
        * monitor/proxy/Makefile.am:
        * monitor/proxy/gproxydrive.c:
        * monitor/proxy/gproxymount.c:
        * monitor/proxy/gproxyvolume.c:
        * monitor/proxy/gproxyvolume.h:
        * monitor/proxy/gproxyvolumemonitor.c:
        * monitor/proxy/gproxyvolumemonitor.h:
        * monitor/proxy/remote-volume-monitor-module.c:
	* monitor/proxy/gproxyshadowmount.[ch]:
	Use the new support for shadow mounts instead
	of g_volume_monitor_adopt_orphan_mount

	Patch from David Zeuthen (#555332)
	
        * programs/gvfs-mount.c:
	Add support to monitor volume monitor events



Added:
   trunk/monitor/proxy/gproxyshadowmount.c
   trunk/monitor/proxy/gproxyshadowmount.h
Modified:
   trunk/ChangeLog
   trunk/client/gdaemonmount.c
   trunk/client/gdaemonvolumemonitor.c
   trunk/monitor/proxy/Makefile.am
   trunk/monitor/proxy/gproxydrive.c
   trunk/monitor/proxy/gproxymount.c
   trunk/monitor/proxy/gproxyvolume.c
   trunk/monitor/proxy/gproxyvolume.h
   trunk/monitor/proxy/gproxyvolumemonitor.c
   trunk/monitor/proxy/gproxyvolumemonitor.h
   trunk/monitor/proxy/remote-volume-monitor-module.c
   trunk/programs/gvfs-mount.c

Modified: trunk/client/gdaemonmount.c
==============================================================================
--- trunk/client/gdaemonmount.c	(original)
+++ trunk/client/gdaemonmount.c	Mon Dec  1 13:58:05 2008
@@ -43,7 +43,6 @@
 
   GMountInfo *mount_info;
 
-  GVolume *foreign_volume;
   GVolumeMonitor *volume_monitor;
 };
 
@@ -60,9 +59,6 @@
   
   mount = G_DAEMON_MOUNT (object);
 
-  if (mount->foreign_volume != NULL)
-    g_object_unref (mount->foreign_volume);
-
   if (mount->volume_monitor != NULL)
     g_object_remove_weak_pointer (G_OBJECT (mount->volume_monitor), (gpointer) &(mount->volume_monitor));
 
@@ -140,24 +136,13 @@
 static GVolume *
 g_daemon_mount_get_volume (GMount *mount)
 {
-  GDaemonMount *daemon_mount = G_DAEMON_MOUNT (mount);
-  if (daemon_mount->foreign_volume != NULL)
-    return g_object_ref (daemon_mount->foreign_volume);
   return NULL;
 }
 
 static GDrive *
 g_daemon_mount_get_drive (GMount *mount)
 {
-  GDaemonMount *daemon_mount = G_DAEMON_MOUNT (mount);
-  GDrive *drive;
-
-  G_LOCK (daemon_mount);
-  drive = NULL;
-  if (daemon_mount->foreign_volume != NULL)
-    drive = g_volume_get_drive (daemon_mount->foreign_volume);
-  G_UNLOCK (daemon_mount);
-  return drive;
+  return NULL;
 }
 
 static gboolean
@@ -169,60 +154,7 @@
 static gboolean
 g_daemon_mount_can_eject (GMount *mount)
 {
-  GDaemonMount *daemon_mount = G_DAEMON_MOUNT (mount);
-  gboolean res;
-  
-  G_LOCK (daemon_mount);
-  res = FALSE;
-  if (daemon_mount->foreign_volume != NULL)
-    res = g_volume_can_eject (daemon_mount->foreign_volume);
-  G_UNLOCK (daemon_mount);
-  
-  return res;
-}
-
-static void
-foreign_volume_removed (GVolume *volume, gpointer user_data)
-{
-  GDaemonMount *daemon_mount = G_DAEMON_MOUNT (user_data);
-
-  G_LOCK (daemon_mount);
-
-  g_object_ref (daemon_mount);
-  
-  if (daemon_mount->foreign_volume == volume)
-    {
-      g_object_unref (daemon_mount->foreign_volume);
-      daemon_mount->foreign_volume = NULL;
-    }
-
-  G_UNLOCK (daemon_mount);
-  
-  g_signal_emit_by_name (daemon_mount, "changed");
-  if (daemon_mount->volume_monitor != NULL)
-    g_signal_emit_by_name (daemon_mount->volume_monitor, "mount_changed", daemon_mount);
-  
-  g_object_unref (daemon_mount);
-}
-
-void
-g_daemon_mount_set_foreign_volume (GDaemonMount *mount, 
-                                   GVolume *foreign_volume)
-{
-  G_LOCK (daemon_mount);
-  
-  if (mount->foreign_volume != NULL)
-    g_object_unref (mount->foreign_volume);
-
-  if (foreign_volume != NULL)
-    {
-      mount->foreign_volume = foreign_volume;
-      g_signal_connect_object (foreign_volume, "removed", (GCallback) foreign_volume_removed, mount, 0);
-    }
-  else
-    mount->foreign_volume = NULL;
-
-  G_UNLOCK (daemon_mount);
+  return FALSE;
 }
 
 static void
@@ -283,80 +215,6 @@
   return TRUE;
 }
 
-typedef struct {
-  GObject *object;
-  GAsyncReadyCallback callback;
-  gpointer user_data;
-} EjectWrapperOp;
-
-static void
-eject_wrapper_callback (GObject *source_object,
-                        GAsyncResult *res,
-                        gpointer user_data)
-{
-  EjectWrapperOp *data  = user_data;
-  data->callback (data->object, res, data->user_data);
-  g_free (data);
-}
-
-static void
-g_daemon_mount_eject (GMount              *mount,
-		      GMountUnmountFlags   flags,
-                      GCancellable        *cancellable,
-                      GAsyncReadyCallback  callback,
-                      gpointer             user_data)
-{
-  GDaemonMount *daemon_mount = G_DAEMON_MOUNT (mount);
-  GDrive *drive;
-
-  G_LOCK (daemon_mount);
-
-  drive = NULL;
-  if (daemon_mount->foreign_volume != NULL)
-    drive = g_volume_get_drive (G_VOLUME (daemon_mount->foreign_volume));
-      
-  G_UNLOCK (daemon_mount);
-  
-  if (drive != NULL)
-    {
-      EjectWrapperOp *data;
-      data = g_new0 (EjectWrapperOp, 1);
-      data->object = G_OBJECT (mount);
-      data->callback = callback;
-      data->user_data = user_data;
-      g_drive_eject (drive, flags, cancellable, eject_wrapper_callback, data);
-      g_object_unref (drive);
-    }
-}
-
-static gboolean
-g_daemon_mount_eject_finish (GMount        *mount,
-			     GAsyncResult  *result,
-			     GError       **error)
-{
-  GDaemonMount *daemon_mount = G_DAEMON_MOUNT (mount);
-  GDrive *drive;
-  gboolean res;
-
-  res = TRUE;
-
-  G_LOCK (daemon_mount);
-
-  drive = NULL;
-  if (daemon_mount->foreign_volume != NULL)
-    drive = g_volume_get_drive (G_VOLUME (daemon_mount->foreign_volume));
-
-  G_UNLOCK (daemon_mount);
-  
-  if (drive != NULL)
-    {
-      res = g_drive_eject_finish (drive, result, error);
-      g_object_unref (drive);
-    }
-  
-  return res;
-}
-
 static char **
 g_daemon_mount_guess_content_type_sync (GMount              *mount,
                                         gboolean             force_rescan,
@@ -414,8 +272,6 @@
   iface->can_eject = g_daemon_mount_can_eject;
   iface->unmount = g_daemon_mount_unmount;
   iface->unmount_finish = g_daemon_mount_unmount_finish;
-  iface->eject = g_daemon_mount_eject;
-  iface->eject_finish = g_daemon_mount_eject_finish;
   iface->guess_content_type = g_daemon_mount_guess_content_type;
   iface->guess_content_type_finish = g_daemon_mount_guess_content_type_finish;
   iface->guess_content_type_sync = g_daemon_mount_guess_content_type_sync;

Modified: trunk/client/gdaemonvolumemonitor.c
==============================================================================
--- trunk/client/gdaemonvolumemonitor.c	(original)
+++ trunk/client/gdaemonvolumemonitor.c	Mon Dec  1 13:58:05 2008
@@ -136,7 +136,6 @@
 mount_added (GDaemonVolumeMonitor *daemon_monitor, GMountInfo *mount_info)
 {
   GDaemonMount *mount;
-  GVolume *volume;
 
   G_LOCK (daemon_vm);
 
@@ -152,9 +151,6 @@
   if (mount_info->user_visible)
     {
       mount = g_daemon_mount_new (mount_info, G_VOLUME_MONITOR (daemon_monitor));
-      volume = g_volume_monitor_adopt_orphan_mount (G_MOUNT (mount));
-      if (volume != NULL)
-        g_daemon_mount_set_foreign_volume (mount, volume);
       daemon_monitor->mounts = g_list_prepend (daemon_monitor->mounts, mount);
 
       /* Ref for the signal emission, other ref is owned by volume monitor */
@@ -204,7 +200,6 @@
   GList *mounts, *l;
   GDaemonMount *mount;
   GMountInfo *info;
-  GVolume *volume;
 
   _the_daemon_volume_monitor = daemon_monitor;
 
@@ -223,9 +218,6 @@
     if (info->user_visible)
       {
         mount = g_daemon_mount_new (info, G_VOLUME_MONITOR (daemon_monitor));
-        volume = g_volume_monitor_adopt_orphan_mount (G_MOUNT (mount));
-        if (volume != NULL)
-          g_daemon_mount_set_foreign_volume (mount, volume);
 	daemon_monitor->mounts = g_list_prepend (daemon_monitor->mounts, mount);
       }
     

Modified: trunk/monitor/proxy/Makefile.am
==============================================================================
--- trunk/monitor/proxy/Makefile.am	(original)
+++ trunk/monitor/proxy/Makefile.am	Mon Dec  1 13:58:05 2008
@@ -12,6 +12,7 @@
 	gproxydrive.c			gproxydrive.h			\
 	gproxyvolume.c			gproxyvolume.h			\
 	gproxymount.c			gproxymount.h			\
+	gproxyshadowmount.c		gproxyshadowmount.h		\
 	gproxyvolumemonitor.c		gproxyvolumemonitor.h		\
 	$(NULL)
 

Modified: trunk/monitor/proxy/gproxydrive.c
==============================================================================
--- trunk/monitor/proxy/gproxydrive.c	(original)
+++ trunk/monitor/proxy/gproxydrive.c	Mon Dec  1 13:58:05 2008
@@ -115,6 +115,9 @@
   GProxyDrive *drive;
   drive = g_object_new (G_TYPE_PROXY_DRIVE, NULL);
   drive->volume_monitor = g_object_ref (volume_monitor);
+  g_object_set_data (G_OBJECT (drive),
+                     "g-proxy-drive-volume-monitor-name",
+                     (gpointer) g_type_name (G_TYPE_FROM_INSTANCE (volume_monitor)));
   return drive;
 }
 

Modified: trunk/monitor/proxy/gproxymount.c
==============================================================================
--- trunk/monitor/proxy/gproxymount.c	(original)
+++ trunk/monitor/proxy/gproxymount.c	Mon Dec  1 13:58:05 2008
@@ -115,6 +115,9 @@
   GProxyMount *mount;
   mount = g_object_new (G_TYPE_PROXY_MOUNT, NULL);
   mount->volume_monitor = g_object_ref (volume_monitor);
+  g_object_set_data (G_OBJECT (mount),
+                     "g-proxy-mount-volume-monitor-name",
+                     (gpointer) g_type_name (G_TYPE_FROM_INSTANCE (volume_monitor)));
   return mount;
 }
 

Added: trunk/monitor/proxy/gproxyshadowmount.c
==============================================================================
--- (empty file)
+++ trunk/monitor/proxy/gproxyshadowmount.c	Mon Dec  1 13:58:05 2008
@@ -0,0 +1,441 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* gvfs - extensions for gio
+ *
+ * Copyright (C) 2006-2008 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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.
+ *
+ * Author: David Zeuthen <davidz redhat com>
+ */
+
+#include <config.h>
+
+#include <string.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+#include <gio/gio.h>
+
+#include <gdbusutils.h>
+
+#include "gproxyvolumemonitor.h"
+#include "gproxyshadowmount.h"
+#include "gproxyvolume.h"
+
+static void signal_emit_in_idle (gpointer object, const char *signal_name, gpointer other_object);
+
+/* Protects all fields of GProxyShadowMount that can change */
+G_LOCK_DEFINE_STATIC(proxy_shadow_mount);
+
+struct _GProxyShadowMount {
+  GObject parent;
+
+  GProxyVolumeMonitor *volume_monitor;
+
+  GProxyVolume *volume;
+  GMount *real_mount;
+  GFile *root;
+};
+
+static void g_proxy_shadow_mount_mount_iface_init (GMountIface *iface);
+
+#define _G_IMPLEMENT_INTERFACE_DYNAMIC(TYPE_IFACE, iface_init)       { \
+  const GInterfaceInfo g_implement_interface_info = { \
+    (GInterfaceInitFunc) iface_init, NULL, NULL \
+  }; \
+  g_type_module_add_interface (type_module, g_define_type_id, TYPE_IFACE, &g_implement_interface_info); \
+}
+G_DEFINE_DYNAMIC_TYPE_EXTENDED (GProxyShadowMount, g_proxy_shadow_mount, G_TYPE_OBJECT, 0,
+                                _G_IMPLEMENT_INTERFACE_DYNAMIC (G_TYPE_MOUNT,
+                                                                g_proxy_shadow_mount_mount_iface_init))
+
+static void
+g_proxy_shadow_mount_finalize (GObject *object)
+{
+  GProxyShadowMount *mount;
+
+  mount = G_PROXY_SHADOW_MOUNT (object);
+
+  g_proxy_shadow_mount_remove (mount);
+
+  if (mount->volume_monitor != NULL)
+    g_object_unref (mount->volume_monitor);
+
+  if (mount->volume != NULL)
+    g_object_unref (mount->volume);
+
+  if (mount->root != NULL)
+    g_object_unref (mount->root);
+
+  if (G_OBJECT_CLASS (g_proxy_shadow_mount_parent_class)->finalize)
+    (*G_OBJECT_CLASS (g_proxy_shadow_mount_parent_class)->finalize) (object);
+}
+
+static void
+g_proxy_shadow_mount_class_init (GProxyShadowMountClass *klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+  gobject_class->finalize = g_proxy_shadow_mount_finalize;
+}
+
+static void
+g_proxy_shadow_mount_class_finalize (GProxyShadowMountClass *klass)
+{
+}
+
+static void
+g_proxy_shadow_mount_init (GProxyShadowMount *proxy_shadow_mount)
+{
+}
+
+void
+g_proxy_shadow_mount_remove (GProxyShadowMount *mount)
+{
+  if (mount->real_mount != NULL)
+    {
+      g_mount_unshadow (mount->real_mount);
+      signal_emit_in_idle (mount->real_mount, "changed", NULL);
+      signal_emit_in_idle (mount->volume_monitor, "mount-changed", mount->real_mount);
+      g_object_unref (mount->real_mount);
+      mount->real_mount = NULL;
+    }
+}
+
+GProxyShadowMount *
+g_proxy_shadow_mount_new (GProxyVolumeMonitor *volume_monitor,
+                          GProxyVolume        *volume,
+                          GMount              *real_mount)
+{
+  GProxyShadowMount *mount;
+  GFile *activation_root;
+
+  mount = NULL;
+
+  activation_root = g_volume_get_activation_root (G_VOLUME (volume));
+  if (activation_root == NULL)
+    {
+      g_warning ("Cannot construct a GProxyShadowMount object for a volume without an activation root");
+      goto out;
+    }
+
+  mount = g_object_new (G_TYPE_PROXY_SHADOW_MOUNT, NULL);
+  mount->volume_monitor = g_object_ref (volume_monitor);
+  mount->volume = g_object_ref (volume);
+  mount->real_mount = g_object_ref (real_mount);
+  mount->root = activation_root;
+
+  g_mount_shadow (mount->real_mount);
+  signal_emit_in_idle (mount->real_mount, "changed", NULL);
+  signal_emit_in_idle (mount->volume_monitor, "mount-changed", mount->real_mount);
+
+  g_object_set_data (G_OBJECT (mount),
+                     "g-proxy-shadow-mount-volume-monitor-name",
+                     (gpointer) g_type_name (G_TYPE_FROM_INSTANCE (volume_monitor)));
+
+ out:
+  return mount;
+}
+
+gboolean
+g_proxy_shadow_mount_has_mount_path (GProxyShadowMount *mount, const char *mount_path)
+{
+  char *path;
+  gboolean result;
+  result = FALSE;
+  path = g_file_get_path (mount->root);
+  if (path != NULL)
+    {
+      if (strcmp (path, mount_path) == 0)
+        result = TRUE;
+      g_free (path);
+    }
+  return result;
+}
+
+static GFile *
+g_proxy_shadow_mount_get_root (GMount *mount)
+{
+  GProxyShadowMount *proxy_shadow_mount = G_PROXY_SHADOW_MOUNT (mount);
+  GFile *root;
+
+  G_LOCK (proxy_shadow_mount);
+  root = g_object_ref (proxy_shadow_mount->root);
+  G_UNLOCK (proxy_shadow_mount);
+  return root;
+}
+
+static GIcon *
+g_proxy_shadow_mount_get_icon (GMount *mount)
+{
+  GProxyShadowMount *proxy_shadow_mount = G_PROXY_SHADOW_MOUNT (mount);
+  GIcon *icon;
+
+  G_LOCK (proxy_shadow_mount);
+  icon = g_volume_get_icon (G_VOLUME (proxy_shadow_mount->volume));
+  G_UNLOCK (proxy_shadow_mount);
+  return icon;
+}
+
+static char *
+g_proxy_shadow_mount_get_uuid (GMount *mount)
+{
+  GProxyShadowMount *proxy_shadow_mount = G_PROXY_SHADOW_MOUNT (mount);
+  char *uuid;
+
+  G_LOCK (proxy_shadow_mount);
+  uuid = g_mount_get_uuid (G_MOUNT (proxy_shadow_mount->real_mount));
+  G_UNLOCK (proxy_shadow_mount);
+  return uuid;
+}
+
+static char *
+g_proxy_shadow_mount_get_name (GMount *mount)
+{
+  GProxyShadowMount *proxy_shadow_mount = G_PROXY_SHADOW_MOUNT (mount);
+  char *name;
+
+  G_LOCK (proxy_shadow_mount);
+  name = g_volume_get_name (G_VOLUME (proxy_shadow_mount->volume));
+  G_UNLOCK (proxy_shadow_mount);
+
+  return name;
+}
+
+static GDrive *
+g_proxy_shadow_mount_get_drive (GMount *mount)
+{
+  GProxyShadowMount *proxy_shadow_mount = G_PROXY_SHADOW_MOUNT (mount);
+  GDrive *drive;
+
+  G_LOCK (proxy_shadow_mount);
+  drive = g_mount_get_drive (G_MOUNT (proxy_shadow_mount->real_mount));
+  G_UNLOCK (proxy_shadow_mount);
+
+  return drive;
+}
+
+static GVolume *
+g_proxy_shadow_mount_get_volume (GMount *mount)
+{
+  GProxyShadowMount *proxy_shadow_mount = G_PROXY_SHADOW_MOUNT (mount);
+  GVolume *volume;
+
+  G_LOCK (proxy_shadow_mount);
+  volume = g_object_ref (proxy_shadow_mount->volume);
+  G_UNLOCK (proxy_shadow_mount);
+
+  return volume;
+}
+
+static gboolean
+g_proxy_shadow_mount_can_unmount (GMount *mount)
+{
+  GProxyShadowMount *proxy_shadow_mount = G_PROXY_SHADOW_MOUNT (mount);
+  gboolean res;
+
+  G_LOCK (proxy_shadow_mount);
+  res = g_mount_can_unmount (G_MOUNT (proxy_shadow_mount->real_mount));
+  G_UNLOCK (proxy_shadow_mount);
+
+  return res;
+}
+
+static gboolean
+g_proxy_shadow_mount_can_eject (GMount *mount)
+{
+  GProxyShadowMount *proxy_shadow_mount = G_PROXY_SHADOW_MOUNT (mount);
+  gboolean res;
+
+  G_LOCK (proxy_shadow_mount);
+  res = g_mount_can_eject (G_MOUNT (proxy_shadow_mount->real_mount));
+  G_UNLOCK (proxy_shadow_mount);
+
+  return res;
+}
+
+static void
+g_proxy_shadow_mount_eject (GMount              *mount,
+                            GMountUnmountFlags   flags,
+                            GCancellable        *cancellable,
+                            GAsyncReadyCallback  callback,
+                            gpointer             user_data)
+{
+  GProxyShadowMount *proxy_shadow_mount = G_PROXY_SHADOW_MOUNT (mount);
+
+  g_mount_eject (proxy_shadow_mount->real_mount,
+                 flags,
+                 cancellable,
+                 callback,
+                 user_data);
+}
+
+static gboolean
+g_proxy_shadow_mount_eject_finish (GMount        *mount,
+                                   GAsyncResult  *result,
+                                   GError       **error)
+{
+  GProxyShadowMount *proxy_shadow_mount = G_PROXY_SHADOW_MOUNT (mount);
+
+  return g_mount_eject_finish (proxy_shadow_mount->real_mount,
+                               result,
+                               error);
+}
+
+static void
+g_proxy_shadow_mount_unmount (GMount              *mount,
+                              GMountUnmountFlags   flags,
+                              GCancellable        *cancellable,
+                              GAsyncReadyCallback  callback,
+                              gpointer             user_data)
+{
+  GProxyShadowMount *proxy_shadow_mount = G_PROXY_SHADOW_MOUNT (mount);
+
+  g_mount_unmount (proxy_shadow_mount->real_mount,
+                   flags,
+                   cancellable,
+                   callback,
+                   user_data);
+}
+
+static gboolean
+g_proxy_shadow_mount_unmount_finish (GMount        *mount,
+                                     GAsyncResult  *result,
+                                     GError       **error)
+{
+  GProxyShadowMount *proxy_shadow_mount = G_PROXY_SHADOW_MOUNT (mount);
+
+  return g_mount_unmount_finish (proxy_shadow_mount->real_mount,
+                                 result,
+                                 error);
+}
+
+static void
+g_proxy_shadow_mount_guess_content_type (GMount              *mount,
+                                         gboolean             force_rescan,
+                                         GCancellable        *cancellable,
+                                         GAsyncReadyCallback  callback,
+                                         gpointer             user_data)
+{
+  GProxyShadowMount *proxy_shadow_mount = G_PROXY_SHADOW_MOUNT (mount);
+
+  g_mount_guess_content_type (proxy_shadow_mount->real_mount,
+                              force_rescan,
+                              cancellable,
+                              callback,
+                              user_data);
+}
+
+static char **
+g_proxy_shadow_mount_guess_content_type_finish (GMount              *mount,
+                                                GAsyncResult        *result,
+                                                GError             **error)
+{
+  GProxyShadowMount *proxy_shadow_mount = G_PROXY_SHADOW_MOUNT (mount);
+
+  return g_mount_guess_content_type_finish (proxy_shadow_mount->real_mount,
+                                            result,
+                                            error);
+}
+
+static char **
+g_proxy_shadow_mount_guess_content_type_sync (GMount              *mount,
+                                              gboolean             force_rescan,
+                                              GCancellable        *cancellable,
+                                              GError             **error)
+{
+  GProxyShadowMount *proxy_shadow_mount = G_PROXY_SHADOW_MOUNT (mount);
+  return g_mount_guess_content_type_sync (proxy_shadow_mount->real_mount,
+                                          force_rescan,
+                                          cancellable,
+                                          error);
+}
+
+GMount *
+g_proxy_shadow_mount_get_real_mount (GProxyShadowMount *mount)
+{
+  return g_object_ref (mount->real_mount);
+}
+
+GFile *
+g_proxy_shadow_mount_get_activation_root (GProxyShadowMount *mount)
+{
+  return g_object_ref (mount->root);
+}
+
+static void
+g_proxy_shadow_mount_mount_iface_init (GMountIface *iface)
+{
+  iface->get_root = g_proxy_shadow_mount_get_root;
+  iface->get_name = g_proxy_shadow_mount_get_name;
+  iface->get_icon = g_proxy_shadow_mount_get_icon;
+  iface->get_uuid = g_proxy_shadow_mount_get_uuid;
+  iface->get_drive = g_proxy_shadow_mount_get_drive;
+  iface->get_volume = g_proxy_shadow_mount_get_volume;
+  iface->can_unmount = g_proxy_shadow_mount_can_unmount;
+  iface->can_eject = g_proxy_shadow_mount_can_eject;
+  iface->unmount = g_proxy_shadow_mount_unmount;
+  iface->unmount_finish = g_proxy_shadow_mount_unmount_finish;
+  iface->eject = g_proxy_shadow_mount_eject;
+  iface->eject_finish = g_proxy_shadow_mount_eject_finish;
+  iface->guess_content_type = g_proxy_shadow_mount_guess_content_type;
+  iface->guess_content_type_finish = g_proxy_shadow_mount_guess_content_type_finish;
+  iface->guess_content_type_sync = g_proxy_shadow_mount_guess_content_type_sync;
+}
+
+void
+g_proxy_shadow_mount_register (GIOModule *module)
+{
+  g_proxy_shadow_mount_register_type (G_TYPE_MODULE (module));
+}
+
+typedef struct {
+  const char *signal_name;
+  GObject *object;
+  GObject *other_object;
+} SignalEmitIdleData;
+
+static gboolean
+signal_emit_in_idle_do (SignalEmitIdleData *data)
+{
+  if (data->other_object != NULL)
+    {
+      g_signal_emit_by_name (data->object, data->signal_name, data->other_object);
+      g_object_unref (data->other_object);
+    }
+  else
+    {
+      g_signal_emit_by_name (data->object, data->signal_name);
+    }
+  g_object_unref (data->object);
+  g_free (data);
+
+  return FALSE;
+}
+
+static void
+signal_emit_in_idle (gpointer object, const char *signal_name, gpointer other_object)
+{
+  SignalEmitIdleData *data;
+
+  data = g_new0 (SignalEmitIdleData, 1);
+  data->signal_name = signal_name;
+  data->object = g_object_ref (G_OBJECT (object));
+  data->other_object = other_object != NULL ? g_object_ref (G_OBJECT (other_object)) : NULL;
+  g_idle_add ((GSourceFunc) signal_emit_in_idle_do, data);
+}

Added: trunk/monitor/proxy/gproxyshadowmount.h
==============================================================================
--- (empty file)
+++ trunk/monitor/proxy/gproxyshadowmount.h	Mon Dec  1 13:58:05 2008
@@ -0,0 +1,59 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* gvfs - extensions for gio
+ *
+ * Copyright (C) 2006-2008 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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.
+ *
+ * Author: David Zeuthen <davidz redhat com>
+ */
+
+#ifndef __G_PROXY_SHADOW_MOUNT_H__
+#define __G_PROXY_SHADOW_MOUNT_H__
+
+#include <glib-object.h>
+#include <gio/gio.h>
+
+#include "gproxyvolumemonitor.h"
+
+G_BEGIN_DECLS
+
+#define G_TYPE_PROXY_SHADOW_MOUNT        (g_proxy_shadow_mount_get_type ())
+#define G_PROXY_SHADOW_MOUNT(o)          (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_PROXY_SHADOW_MOUNT, GProxyShadowMount))
+#define G_PROXY_SHADOW_MOUNT_CLASS(k)    (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_PROXY_SHADOW_MOUNT, GProxyShadowMountClass))
+#define G_IS_PROXY_SHADOW_MOUNT(o)       (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_PROXY_SHADOW_MOUNT))
+#define G_IS_PROXY_SHADOW_MOUNT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_PROXY_SHADOW_MOUNT))
+
+typedef struct _GProxyShadowMountClass GProxyShadowMountClass;
+
+struct _GProxyShadowMountClass {
+   GObjectClass parent_class;
+};
+
+GType              g_proxy_shadow_mount_get_type            (void) G_GNUC_CONST;
+void               g_proxy_shadow_mount_register            (GIOModule           *module);
+GProxyShadowMount *g_proxy_shadow_mount_new                 (GProxyVolumeMonitor *volume_monitor,
+                                                             GProxyVolume        *volume,
+                                                             GMount              *real_mount);
+GMount            *g_proxy_shadow_mount_get_real_mount      (GProxyShadowMount   *mount);
+GFile             *g_proxy_shadow_mount_get_activation_root (GProxyShadowMount   *mount);
+gboolean           g_proxy_shadow_mount_has_mount_path      (GProxyShadowMount   *mount,
+                                                             const char          *mount_path);
+void               g_proxy_shadow_mount_remove              (GProxyShadowMount   *mount);
+
+G_END_DECLS
+
+#endif /* __G_PROXY_SHADOW_MOUNT_H__ */

Modified: trunk/monitor/proxy/gproxyvolume.c
==============================================================================
--- trunk/monitor/proxy/gproxyvolume.c	(original)
+++ trunk/monitor/proxy/gproxyvolume.c	Mon Dec  1 13:58:05 2008
@@ -37,6 +37,8 @@
 #include "gproxyvolume.h"
 #include "gproxymount.h"
 
+static void signal_emit_in_idle (gpointer object, const char *signal_name, gpointer other_object);
+
 /* Protects all fields of GProxyVolume that can change */
 G_LOCK_DEFINE_STATIC(proxy_volume);
 
@@ -45,6 +47,9 @@
 
   GProxyVolumeMonitor *volume_monitor;
 
+  /* non-NULL only if activation_uri != NULL */
+  GVolumeMonitor *union_monitor;
+
   char *id;
   char *name;
   char *uuid;
@@ -54,10 +59,10 @@
   char *mount_id;
   GHashTable *identifiers;
 
-  GMount *foreign_mount;
-
   gboolean can_mount;
   gboolean should_automount;
+
+  GProxyShadowMount *shadow_mount;
 };
 
 static void g_proxy_volume_volume_iface_init (GVolumeIface *iface);
@@ -73,6 +78,30 @@
                                 _G_IMPLEMENT_INTERFACE_DYNAMIC (G_TYPE_VOLUME,
                                                                 g_proxy_volume_volume_iface_init))
 
+
+static void union_monitor_mount_added (GVolumeMonitor *union_monitor,
+                                       GMount         *mount,
+                                       GProxyVolume   *volume);
+
+static void union_monitor_mount_removed (GVolumeMonitor *union_monitor,
+                                         GMount         *mount,
+                                         GProxyVolume   *volume);
+
+static void union_monitor_mount_changed (GVolumeMonitor *union_monitor,
+                                         GMount         *mount,
+                                         GProxyVolume   *volume);
+
+static void update_shadow_mount (GProxyVolume *volume);
+
+GProxyShadowMount *
+g_proxy_volume_get_shadow_mount (GProxyVolume *volume)
+{
+  if (volume->shadow_mount != NULL)
+    return g_object_ref (volume->shadow_mount);
+  else
+    return NULL;
+}
+
 static void
 g_proxy_volume_finalize (GObject *object)
 {
@@ -91,11 +120,26 @@
   if (volume->identifiers != NULL)
     g_hash_table_unref (volume->identifiers);
 
-  if (volume->foreign_mount != NULL)
-    g_object_unref (volume->foreign_mount);
+  if (volume->shadow_mount != NULL)
+    {
+      signal_emit_in_idle (volume->shadow_mount, "unmounted", NULL);
+      signal_emit_in_idle (volume->volume_monitor, "mount-removed", volume->shadow_mount);
+      g_proxy_shadow_mount_remove (volume->shadow_mount);
+      g_object_unref (volume->shadow_mount);
+    }
+
+  if (volume->union_monitor != NULL)
+    {
+      g_signal_handlers_disconnect_by_func (volume->union_monitor, union_monitor_mount_added, volume);
+      g_signal_handlers_disconnect_by_func (volume->union_monitor, union_monitor_mount_removed, volume);
+      g_signal_handlers_disconnect_by_func (volume->union_monitor, union_monitor_mount_changed, volume);
+      g_object_unref (volume->union_monitor);
+    }
 
   if (volume->volume_monitor != NULL)
-    g_object_unref (volume->volume_monitor);
+    {
+      g_object_unref (volume->volume_monitor);
+    }
 
   if (G_OBJECT_CLASS (g_proxy_volume_parent_class)->finalize)
     (*G_OBJECT_CLASS (g_proxy_volume_parent_class)->finalize) (object);
@@ -125,53 +169,159 @@
   GProxyVolume *volume;
   volume = g_object_new (G_TYPE_PROXY_VOLUME, NULL);
   volume->volume_monitor = g_object_ref (volume_monitor);
+  g_object_set_data (G_OBJECT (volume),
+                     "g-proxy-volume-volume-monitor-name",
+                     (gpointer) g_type_name (G_TYPE_FROM_INSTANCE (volume_monitor)));
   return volume;
 }
 
-static gboolean
-changed_in_idle (gpointer data)
-{
-  GProxyVolume *volume = data;
-
-  g_signal_emit_by_name (volume, "changed");
-  if (volume->volume_monitor != NULL)
-    g_signal_emit_by_name (volume->volume_monitor, "volume-changed", volume);
-  g_object_unref (volume);
 
-  return FALSE;
+static void
+union_monitor_mount_added (GVolumeMonitor *union_monitor,
+                           GMount         *mount,
+                           GProxyVolume   *volume)
+{
+  update_shadow_mount (volume);
 }
 
 static void
-foreign_mount_unmounted (GMount *mount, gpointer user_data)
+union_monitor_mount_removed (GVolumeMonitor *union_monitor,
+                             GMount         *mount,
+                             GProxyVolume   *volume)
 {
-  GProxyVolume *volume = G_PROXY_VOLUME (user_data);
-  gboolean check;
+  update_shadow_mount (volume);
+}
 
-  G_LOCK (proxy_volume);
-  check = (volume->foreign_mount == mount);
-  G_UNLOCK (proxy_volume);
-  if (check)
-    g_proxy_volume_adopt_foreign_mount (volume, NULL);
+static void
+union_monitor_mount_changed (GVolumeMonitor *union_monitor,
+                             GMount         *mount,
+                             GProxyVolume   *volume)
+{
+  if (volume->shadow_mount != NULL)
+    {
+      GMount *real_mount;
+      real_mount = g_proxy_shadow_mount_get_real_mount (volume->shadow_mount);
+      if (mount == real_mount)
+        {
+          signal_emit_in_idle (volume->shadow_mount, "changed", NULL);
+          signal_emit_in_idle (volume->volume_monitor, "mount-changed", volume->shadow_mount);
+        }
+      g_object_unref (real_mount);
+    }
 }
 
-void
-g_proxy_volume_adopt_foreign_mount (GProxyVolume *volume,
-                                    GMount       *foreign_mount)
+static void
+update_shadow_mount (GProxyVolume *volume)
 {
-  G_LOCK (proxy_volume);
-  if (volume->foreign_mount != NULL)
-    g_object_unref (volume->foreign_mount);
+  GFile *activation_root;
+  GList *mounts;
+  GList *l;
+  GMount *mount_to_shadow;
+
+  activation_root = NULL;
+  mount_to_shadow = NULL;
+
+  if (volume->activation_uri == NULL)
+    goto out;
+
+  activation_root = g_file_new_for_uri (volume->activation_uri);
+
+  if (volume->union_monitor == NULL)
+    {
+      volume->union_monitor = g_volume_monitor_get ();
+      g_signal_connect (volume->union_monitor, "mount-added", (GCallback) union_monitor_mount_added, volume);
+      g_signal_connect (volume->union_monitor, "mount-removed", (GCallback) union_monitor_mount_removed, volume);
+      g_signal_connect (volume->union_monitor, "mount-changed", (GCallback) union_monitor_mount_changed, volume);
+    }
+
+  mounts = g_volume_monitor_get_mounts (volume->union_monitor);
+  for (l = mounts; l != NULL; l = l->next)
+    {
+      GMount *mount = G_MOUNT (l->data);
+      GFile *mount_root;
+
+      /* don't consider our (possibly) existing shadow mount */
+      if (G_IS_PROXY_SHADOW_MOUNT (mount))
+        continue;
+
+      mount_root = g_mount_get_root (mount);
+      if (g_file_has_prefix (activation_root, mount_root))
+        {
+          mount_to_shadow = g_object_ref (mount);
+          break;
+        }
+    }
+  g_list_foreach (mounts, (GFunc) g_object_unref, NULL);
+  g_list_free (mounts);
 
-  if (foreign_mount != NULL)
+  if (mount_to_shadow != NULL)
     {
-      volume->foreign_mount =  g_object_ref (foreign_mount);
-      g_signal_connect_object (foreign_mount, "unmounted", (GCallback) foreign_mount_unmounted, volume, 0);
+      /* there's now a mount to shadow, if we don't have a GProxyShadowMount then create one */
+      if (volume->shadow_mount == NULL)
+        {
+          volume->shadow_mount = g_proxy_shadow_mount_new (volume->volume_monitor,
+                                                           volume,
+                                                           mount_to_shadow);
+          signal_emit_in_idle (volume->volume_monitor, "mount-added", volume->shadow_mount);
+        }
+      else
+        {
+          GFile *current_activation_root;
+
+          /* we have a GProxyShadowMount already. However, we need to replace it if the
+           * activation root has changed.
+           */
+          current_activation_root = g_proxy_shadow_mount_get_activation_root (volume->shadow_mount);
+          if (!g_file_equal (current_activation_root, activation_root))
+            {
+              signal_emit_in_idle (volume->shadow_mount, "unmounted", NULL);
+              signal_emit_in_idle (volume->volume_monitor, "mount-removed", volume->shadow_mount);
+              g_proxy_shadow_mount_remove (volume->shadow_mount);
+              g_object_unref (volume->shadow_mount);
+              volume->shadow_mount = NULL;
+
+              volume->shadow_mount = g_proxy_shadow_mount_new (volume->volume_monitor,
+                                                               volume,
+                                                               mount_to_shadow);
+              signal_emit_in_idle (volume->volume_monitor, "mount-added", volume->shadow_mount);
+            }
+          g_object_unref (current_activation_root);
+        }
     }
   else
-    volume->foreign_mount =  NULL;
+    {
+      /* no mount to shadow; if we have a GProxyShadowMount then remove it */
+      if (volume->shadow_mount != NULL)
+        {
+          signal_emit_in_idle (volume->shadow_mount, "unmounted", NULL);
+          signal_emit_in_idle (volume->volume_monitor, "mount-removed", volume->shadow_mount);
+          g_proxy_shadow_mount_remove (volume->shadow_mount);
+          g_object_unref (volume->shadow_mount);
+          volume->shadow_mount = NULL;
+        }
+    }
 
-  g_idle_add (changed_in_idle, g_object_ref (volume));
-  G_UNLOCK (proxy_volume);
+ out:
+
+  if (activation_root != NULL)
+    g_object_unref (activation_root);
+
+  if (mount_to_shadow != NULL)
+    g_object_unref (mount_to_shadow);
+}
+
+static gboolean
+update_shadow_mount_in_idle_do (GProxyVolume *volume)
+{
+  update_shadow_mount (volume);
+  g_object_unref (volume);
+  return FALSE;
+}
+
+static void
+update_shadow_mount_in_idle (GProxyVolume *volume)
+{
+  g_idle_add ((GSourceFunc) update_shadow_mount_in_idle_do, g_object_ref (volume));
 }
 
 /* string               id
@@ -264,6 +414,9 @@
   volume->should_automount = should_automount;
   volume->identifiers = identifiers != NULL ? g_hash_table_ref (identifiers) : NULL;
 
+  /* this calls into the union monitor; do it in idle to avoid locking issues */
+  update_shadow_mount_in_idle (volume);
+
  out:
   g_hash_table_unref (identifiers);
 }
@@ -381,22 +534,21 @@
   GProxyVolume *proxy_volume = G_PROXY_VOLUME (volume);
   GMount *mount;
 
+  mount = NULL;
+
   G_LOCK (proxy_volume);
-  if (proxy_volume->foreign_mount != NULL)
+
+  if (proxy_volume->shadow_mount != NULL)
     {
-      mount = g_object_ref (proxy_volume->foreign_mount);
+      mount = g_object_ref (proxy_volume->shadow_mount);
     }
-  else
+  else if (proxy_volume->mount_id != NULL && strlen (proxy_volume->mount_id) > 0)
     {
-      mount = NULL;
-      if (proxy_volume->mount_id != NULL && strlen (proxy_volume->mount_id) > 0)
-        {
-          GProxyMount *proxy_mount;
-          proxy_mount = g_proxy_volume_monitor_get_mount_for_id (proxy_volume->volume_monitor,
-                                                                 proxy_volume->mount_id);
-          if (proxy_mount != NULL)
-            mount = G_MOUNT (proxy_mount);
-        }
+      GProxyMount *proxy_mount;
+      proxy_mount = g_proxy_volume_monitor_get_mount_for_id (proxy_volume->volume_monitor,
+                                                             proxy_volume->mount_id);
+      if (proxy_mount != NULL)
+        mount = G_MOUNT (proxy_mount);
     }
   G_UNLOCK (proxy_volume);
 
@@ -690,3 +842,39 @@
 {
   g_proxy_volume_register_type (G_TYPE_MODULE (module));
 }
+
+typedef struct {
+  const char *signal_name;
+  GObject *object;
+  GObject *other_object;
+} SignalEmitIdleData;
+
+static gboolean
+signal_emit_in_idle_do (SignalEmitIdleData *data)
+{
+  if (data->other_object != NULL)
+    {
+      g_signal_emit_by_name (data->object, data->signal_name, data->other_object);
+      g_object_unref (data->other_object);
+    }
+  else
+    {
+      g_signal_emit_by_name (data->object, data->signal_name);
+    }
+  g_object_unref (data->object);
+  g_free (data);
+
+  return FALSE;
+}
+
+static void
+signal_emit_in_idle (gpointer object, const char *signal_name, gpointer other_object)
+{
+  SignalEmitIdleData *data;
+
+  data = g_new0 (SignalEmitIdleData, 1);
+  data->signal_name = signal_name;
+  data->object = g_object_ref (G_OBJECT (object));
+  data->other_object = other_object != NULL ? g_object_ref (G_OBJECT (other_object)) : NULL;
+  g_idle_add ((GSourceFunc) signal_emit_in_idle_do, data);
+}

Modified: trunk/monitor/proxy/gproxyvolume.h
==============================================================================
--- trunk/monitor/proxy/gproxyvolume.h	(original)
+++ trunk/monitor/proxy/gproxyvolume.h	Mon Dec  1 13:58:05 2008
@@ -28,6 +28,7 @@
 #include <gio/gio.h>
 
 #include "gproxyvolumemonitor.h"
+#include "gproxyshadowmount.h"
 
 G_BEGIN_DECLS
 
@@ -48,10 +49,9 @@
 void          g_proxy_volume_update              (GProxyVolume        *volume,
                                                   DBusMessageIter     *iter);
 const char   *g_proxy_volume_get_id              (GProxyVolume        *volume);
-void          g_proxy_volume_adopt_foreign_mount (GProxyVolume        *volume,
-                                                  GMount              *foreign_mount);
 void          g_proxy_volume_register            (GIOModule           *module);
 
+GProxyShadowMount *g_proxy_volume_get_shadow_mount (GProxyVolume        *volume);
 
 G_END_DECLS
 

Modified: trunk/monitor/proxy/gproxyvolumemonitor.c
==============================================================================
--- trunk/monitor/proxy/gproxyvolumemonitor.c	(original)
+++ trunk/monitor/proxy/gproxyvolumemonitor.c	Mon Dec  1 13:58:05 2008
@@ -162,6 +162,7 @@
   GList *l;
   GHashTableIter hash_iter;
   GProxyMount *mount;
+  GProxyVolume *volume;
 
   monitor = G_PROXY_VOLUME_MONITOR (volume_monitor);
   l = NULL;
@@ -172,6 +173,16 @@
   while (g_hash_table_iter_next (&hash_iter, NULL, (gpointer) &mount))
     l = g_list_append (l, g_object_ref (mount));
 
+  /* also return shadow mounts */
+  g_hash_table_iter_init (&hash_iter, monitor->volumes);
+  while (g_hash_table_iter_next (&hash_iter, NULL, (gpointer) &volume))
+    {
+      GProxyShadowMount *shadow_mount;
+      shadow_mount = g_proxy_volume_get_shadow_mount (volume);
+      if (shadow_mount != NULL)
+        l = g_list_append (l, shadow_mount);
+    }
+
   G_UNLOCK (proxy_vm);
 
   return l;
@@ -534,9 +545,19 @@
         volume = g_hash_table_lookup (monitor->volumes, id);
         if (volume != NULL)
           {
+            GProxyShadowMount *shadow_mount;
+
             g_proxy_volume_update (volume, &iter);
             signal_emit_in_idle (volume, "changed", NULL);
             signal_emit_in_idle (monitor, "volume-changed", volume);
+
+            shadow_mount = g_proxy_volume_get_shadow_mount (volume);
+            if (shadow_mount != NULL)
+              {
+                signal_emit_in_idle (shadow_mount, "changed", NULL);
+                signal_emit_in_idle (monitor, "mount-changed", shadow_mount);
+                g_object_unref (shadow_mount);
+              }
           }
       }
     else if (strcmp (member, "VolumeAdded") == 0)
@@ -743,56 +764,6 @@
   return res;
 }
 
-static GVolume *
-adopt_orphan_mount (GMount *mount, GVolumeMonitor *monitor)
-{
-  GProxyVolumeMonitor *proxy_monitor = G_PROXY_VOLUME_MONITOR (monitor);
-  GFile *mount_root;
-  GProxyVolume *proxy_volume;
-  GVolume *ret;
-  GHashTableIter hash_iter;
-
-  ret = NULL;
-
-  G_LOCK (proxy_vm);
-
-  mount_root = g_mount_get_root (mount);
-
-  /* TODO: consider what happens if two volumes wants to adopt the same mount?
-   *
-   * e.g. imagine two GVolume objects with activation_roots
-   *
-   *      ssh://server/dir1
-   *      ssh://server/dir2
-   */
-
-  g_hash_table_iter_init (&hash_iter, proxy_monitor->volumes);
-  while (g_hash_table_iter_next (&hash_iter, NULL, (gpointer) &proxy_volume))
-    {
-      GFile *activation_root;
-
-      activation_root = g_volume_get_activation_root (G_VOLUME (proxy_volume));
-      if (activation_root != NULL)
-        {
-          if (g_file_has_prefix (activation_root, mount_root) ||
-              g_file_equal (activation_root, mount_root))
-            {
-              g_proxy_volume_adopt_foreign_mount (proxy_volume, mount);
-              ret = g_object_ref (proxy_volume);
-              g_object_unref (activation_root);
-              goto found;
-            }
-          g_object_unref (activation_root);
-        }
-    }
-
- found:
-  g_object_unref (mount_root);
-
-  G_UNLOCK (proxy_vm);
-  return ret;
-}
-
 static void
 g_proxy_volume_monitor_class_init (GProxyVolumeMonitorClass *klass)
 {
@@ -809,7 +780,6 @@
   monitor_class->get_connected_drives = get_connected_drives;
   monitor_class->get_volume_for_uuid = get_volume_for_uuid;
   monitor_class->get_mount_for_uuid = get_mount_for_uuid;
-  monitor_class->adopt_orphan_mount = adopt_orphan_mount;
 
   i = klass->is_supported_nr;
   is_supported_classes[i] = klass;

Modified: trunk/monitor/proxy/gproxyvolumemonitor.h
==============================================================================
--- trunk/monitor/proxy/gproxyvolumemonitor.h	(original)
+++ trunk/monitor/proxy/gproxyvolumemonitor.h	Mon Dec  1 13:58:05 2008
@@ -44,6 +44,7 @@
 typedef struct _GProxyDrive GProxyDrive;
 typedef struct _GProxyVolume GProxyVolume;
 typedef struct _GProxyMount GProxyMount;
+typedef struct _GProxyShadowMount GProxyShadowMount;
 
 struct _GProxyVolumeMonitorClass {
   GNativeVolumeMonitorClass parent_class;

Modified: trunk/monitor/proxy/remote-volume-monitor-module.c
==============================================================================
--- trunk/monitor/proxy/remote-volume-monitor-module.c	(original)
+++ trunk/monitor/proxy/remote-volume-monitor-module.c	Mon Dec  1 13:58:05 2008
@@ -31,6 +31,7 @@
 #include "gproxyvolumemonitor.h"
 #include "gproxyvolume.h"
 #include "gproxymount.h"
+#include "gproxyshadowmount.h"
 #include "gproxydrive.h"
 
 void
@@ -45,6 +46,7 @@
 
   g_proxy_drive_register (module);
   g_proxy_mount_register (module);
+  g_proxy_shadow_mount_register (module);
   g_proxy_volume_register (module);
   g_proxy_volume_monitor_register (module);
 out:

Modified: trunk/programs/gvfs-mount.c
==============================================================================
--- trunk/programs/gvfs-mount.c	(original)
+++ trunk/programs/gvfs-mount.c	Mon Dec  1 13:58:05 2008
@@ -43,7 +43,8 @@
 static gboolean mount_mountable = FALSE;
 static gboolean mount_unmount = FALSE;
 static gboolean mount_list = FALSE;
-static gboolean mount_list_info = FALSE;
+static gboolean extra_detail = FALSE;
+static gboolean mount_monitor = FALSE;
 static const char *unmount_scheme = NULL;
 
 static const GOptionEntry entries[] = 
@@ -52,7 +53,8 @@
   { "unmount", 'u', 0, G_OPTION_ARG_NONE, &mount_unmount, "Unmount", NULL},
   { "unmount-scheme", 's', 0, G_OPTION_ARG_STRING, &unmount_scheme, "Unmount all mounts with the given scheme", NULL},
   { "list", 'l', 0, G_OPTION_ARG_NONE, &mount_list, "List", NULL},
-  { "list-info", 'i', 0, G_OPTION_ARG_NONE, &mount_list_info, "List extra information", NULL},
+  { "detail", 'i', 0, G_OPTION_ARG_NONE, &extra_detail, "Show extra information for List and Monitor", NULL},
+  { "monitor", 'o', 0, G_OPTION_ARG_NONE, &mount_monitor, "Monitor events", NULL},
   { NULL }
 };
 
@@ -292,6 +294,50 @@
   g_strfreev (names);
 }
 
+/* don't copy-paste this code */
+static char *
+get_type_name (gpointer object)
+{
+  const char *type_name;
+  char *ret;
+
+  type_name = g_type_name (G_TYPE_FROM_INSTANCE (object));
+  if (strcmp ("GProxyDrive", type_name) == 0)
+    {
+      ret = g_strdup_printf ("%s (%s)",
+                             type_name,
+                             (const char *) g_object_get_data (G_OBJECT (object),
+                                                               "g-proxy-drive-volume-monitor-name"));
+    }
+  else if (strcmp ("GProxyVolume", type_name) == 0)
+    {
+      ret = g_strdup_printf ("%s (%s)",
+                             type_name,
+                             (const char *) g_object_get_data (G_OBJECT (object),
+                                                               "g-proxy-volume-volume-monitor-name"));
+    }
+  else if (strcmp ("GProxyMount", type_name) == 0)
+    {
+      ret = g_strdup_printf ("%s (%s)",
+                             type_name,
+                             (const char *) g_object_get_data (G_OBJECT (object),
+                                                               "g-proxy-mount-volume-monitor-name"));
+    }
+  else if (strcmp ("GProxyShadowMount", type_name) == 0)
+    {
+      ret = g_strdup_printf ("%s (%s)",
+                             type_name,
+                             (const char *) g_object_get_data (G_OBJECT (object),
+                                                               "g-proxy-shadow-mount-volume-monitor-name"));
+    }
+  else
+    {
+      ret = g_strdup (type_name);
+    }
+
+  return ret;
+}
+
 static void
 list_mounts (GList *mounts,
 	     int indent,
@@ -305,6 +351,7 @@
   GFile *root;
   GIcon *icon;
   char **x_content_types;
+  char *type_name;
   
   for (c = 0, l = mounts; l != NULL; l = l->next, c++)
     {
@@ -315,7 +362,7 @@
 	  volume = g_mount_get_volume (mount);
 	  if (volume != NULL)
 	    {
-	      g_object_unref (volume);
+              g_object_unref (volume);
 	      continue;
 	    }
 	}
@@ -326,7 +373,11 @@
       
       g_print ("%*sMount(%d): %s -> %s\n", indent, "", c, name, uri);
 
-      if (mount_list_info)
+      type_name = get_type_name (mount);
+      g_print ("%*sType: %s\n", indent+2, "", type_name);
+      g_free (type_name);
+
+      if (extra_detail)
 	{
 	  uuid = g_mount_get_uuid (mount);
 	  if (uuid)
@@ -354,6 +405,7 @@
 
 	  g_print ("%*scan_unmount=%d\n", indent + 2, "", g_mount_can_unmount (mount));
 	  g_print ("%*scan_eject=%d\n", indent + 2, "", g_mount_can_eject (mount));
+	  g_print ("%*sis_shadowed=%d\n", indent + 2, "", g_mount_is_shadowed (mount));
 	  g_free (uuid);
 	}
       
@@ -378,6 +430,7 @@
   GFile *activation_root;
   char **ids;
   GIcon *icon;
+  char *type_name;
   
   for (c = 0, l = volumes; l != NULL; l = l->next, c++)
     {
@@ -398,7 +451,11 @@
       g_print ("%*sVolume(%d): %s\n", indent, "", c, name);
       g_free (name);
 
-      if (mount_list_info)
+      type_name = get_type_name (volume);
+      g_print ("%*sType: %s\n", indent+2, "", type_name);
+      g_free (type_name);
+
+      if (extra_detail)
 	{
 	  ids = g_volume_enumerate_identifiers (volume);
 	  if (ids && ids[0] != NULL)
@@ -461,6 +518,7 @@
   char *name;
   char **ids;
   GIcon *icon;
+  char *type_name;
   
   for (c = 0, l = drives; l != NULL; l = l->next, c++)
     {
@@ -469,8 +527,12 @@
       
       g_print ("%*sDrive(%d): %s\n", indent, "", c, name);
       g_free (name);
+
+      type_name = get_type_name (drive);
+      g_print ("%*sType: %s\n", indent+2, "", type_name);
+      g_free (type_name);
       
-      if (mount_list_info)
+      if (extra_detail)
 	{
 	  ids = g_drive_enumerate_identifiers (drive);
 	  if (ids && ids[0] != NULL)
@@ -567,6 +629,180 @@
   g_object_unref (volume_monitor);
 }
 
+static void
+monitor_print_mount (GMount *mount)
+{
+  if (extra_detail)
+    {
+      GList *l;
+      l = g_list_prepend (NULL, mount);
+      list_mounts (l, 2, FALSE);
+      g_list_free (l);
+      g_print ("\n");
+    }
+}
+
+static void
+monitor_print_volume (GVolume *volume)
+{
+  if (extra_detail)
+    {
+      GList *l;
+      l = g_list_prepend (NULL, volume);
+      list_volumes (l, 2, FALSE);
+      g_list_free (l);
+      g_print ("\n");
+    }
+}
+
+static void
+monitor_print_drive (GDrive *drive)
+{
+  if (extra_detail)
+    {
+      GList *l;
+      l = g_list_prepend (NULL, drive);
+      list_drives (l, 2);
+      g_list_free (l);
+      g_print ("\n");
+    }
+}
+
+static void
+monitor_mount_added (GVolumeMonitor *volume_monitor, GMount *mount)
+{
+  char *name;
+  name = g_mount_get_name (mount);
+  g_print ("Mount added: '%s'\n", name);
+  g_free (name);
+  monitor_print_mount (mount);
+}
+
+static void
+monitor_mount_removed (GVolumeMonitor *volume_monitor, GMount *mount)
+{
+  char *name;
+  name = g_mount_get_name (mount);
+  g_print ("Mount removed: '%s'\n", name);
+  g_free (name);
+  monitor_print_mount (mount);
+}
+
+static void
+monitor_mount_changed (GVolumeMonitor *volume_monitor, GMount *mount)
+{
+  char *name;
+  name = g_mount_get_name (mount);
+  g_print ("Mount changed: '%s'\n", name);
+  g_free (name);
+  monitor_print_mount (mount);
+}
+
+static void
+monitor_mount_pre_unmount (GVolumeMonitor *volume_monitor, GMount *mount)
+{
+  char *name;
+  name = g_mount_get_name (mount);
+  g_print ("Mount pre-unmount:  '%s'\n", name);
+  g_free (name);
+  monitor_print_mount (mount);
+}
+
+static void
+monitor_volume_added (GVolumeMonitor *volume_monitor, GVolume *volume)
+{
+  char *name;
+  name = g_volume_get_name (volume);
+  g_print ("Volume added:       '%s'\n", name);
+  g_free (name);
+  monitor_print_volume (volume);
+}
+
+static void
+monitor_volume_removed (GVolumeMonitor *volume_monitor, GVolume *volume)
+{
+  char *name;
+  name = g_volume_get_name (volume);
+  g_print ("Volume removed:     '%s'\n", name);
+  g_free (name);
+  monitor_print_volume (volume);
+}
+
+static void
+monitor_volume_changed (GVolumeMonitor *volume_monitor, GVolume *volume)
+{
+  char *name;
+  name = g_volume_get_name (volume);
+  g_print ("Volume changed:     '%s'\n", name);
+  g_free (name);
+  monitor_print_volume (volume);
+}
+
+static void
+monitor_drive_connected (GVolumeMonitor *volume_monitor, GDrive *drive)
+{
+  char *name;
+  name = g_drive_get_name (drive);
+  g_print ("Drive connected:    '%s'\n", name);
+  g_free (name);
+  monitor_print_drive (drive);
+}
+
+static void
+monitor_drive_disconnected (GVolumeMonitor *volume_monitor, GDrive *drive)
+{
+  char *name;
+  name = g_drive_get_name (drive);
+  g_print ("Drive disconnected: '%s'\n", name);
+  g_free (name);
+  monitor_print_drive (drive);
+}
+
+static void
+monitor_drive_changed (GVolumeMonitor *volume_monitor, GDrive *drive)
+{
+  char *name;
+  name = g_drive_get_name (drive);
+  g_print ("Drive changed:      '%s'\n", name);
+  g_free (name);
+  monitor_print_drive (drive);
+}
+
+static void
+monitor_drive_eject_button (GVolumeMonitor *volume_monitor, GDrive *drive)
+{
+  char *name;
+  name = g_drive_get_name (drive);
+  g_print ("Drive eject button: '%s'\n", name);
+  g_free (name);
+}
+
+static void
+monitor (void)
+{
+  GMainLoop *loop;
+  GVolumeMonitor *volume_monitor;
+
+  loop = g_main_loop_new (NULL, FALSE);
+  volume_monitor = g_volume_monitor_get ();
+
+  g_signal_connect (volume_monitor, "mount-added", (GCallback) monitor_mount_added, NULL);
+  g_signal_connect (volume_monitor, "mount-removed", (GCallback) monitor_mount_removed, NULL);
+  g_signal_connect (volume_monitor, "mount-changed", (GCallback) monitor_mount_changed, NULL);
+  g_signal_connect (volume_monitor, "mount-pre-unmount", (GCallback) monitor_mount_pre_unmount, NULL);
+  g_signal_connect (volume_monitor, "volume-added", (GCallback) monitor_volume_added, NULL);
+  g_signal_connect (volume_monitor, "volume-removed", (GCallback) monitor_volume_removed, NULL);
+  g_signal_connect (volume_monitor, "volume-changed", (GCallback) monitor_volume_changed, NULL);
+  g_signal_connect (volume_monitor, "drive-connected", (GCallback) monitor_drive_connected, NULL);
+  g_signal_connect (volume_monitor, "drive-disconnected", (GCallback) monitor_drive_disconnected, NULL);
+  g_signal_connect (volume_monitor, "drive-changed", (GCallback) monitor_drive_changed, NULL);
+  g_signal_connect (volume_monitor, "drive-eject-button", (GCallback) monitor_drive_eject_button, NULL);
+
+  g_print ("Monitoring events. Press Ctrl+C to quit.\n");
+
+  g_main_loop_run (main_loop);
+}
+
 int
 main (int argc, char *argv[])
 {
@@ -592,6 +828,10 @@
     {
       unmount_all_with_scheme (unmount_scheme);
     }
+  else if (mount_monitor)
+    {
+      monitor ();
+    }
   else if (argc > 1)
     {
       int i;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]