summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog13
-rw-r--r--acconfig.h1
-rw-r--r--configure.in21
-rw-r--r--libnautilus-private/nautilus-monitor.c375
4 files changed, 109 insertions, 301 deletions
diff --git a/ChangeLog b/ChangeLog
index 3b7fdb92f..2f9244cda 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2002-05-22 Alex Graveley <alex@ximian.com>
+
+ * configure.in: Remove FAM check.
+
+ * acconfig.h: Remove HAVE_LIBFAM.
+
+ * libnautilus-private/nautilus-monitor.[ch]: Convert to using
+ gnome-vfs monitors. nautilus_monitor_active() now checks if FAM
+ can be used by creating a monitor for the user's desktop
+ directory, and caches this if successful. Adds an idle handler to
+ call nautilus_file_changes_consume_changes(), so multiple file
+ changes have a chance of being chunked together.
+
2002-05-22 Bastien Nocera <hadess@hadess.net>
reviewed by: Alex Larsson <alexl@redhat.com>
diff --git a/acconfig.h b/acconfig.h
index 830d7d25b..4baeb3d75 100644
--- a/acconfig.h
+++ b/acconfig.h
@@ -6,7 +6,6 @@
#undef HAVE_GETTEXT
#undef HAVE_LC_MESSAGES
#undef HAVE_LIBBZ2
-#undef HAVE_LIBFAM
#undef HAVE_LIBJPEG
#undef HAVE_MEDUSA
#undef HAVE_STPCPY
diff --git a/configure.in b/configure.in
index a7d5406da..12076e29f 100644
--- a/configure.in
+++ b/configure.in
@@ -106,25 +106,6 @@ AC_CHECK_FUNCS(setenv unsetenv putenv)
dnl ==========================================================================
-dnl FAM
-
-AC_LANG_SAVE
-AC_LANG_CPLUSPLUS
-
-FAM_MISSING_WARNING="Nautilus depends on FAM to provide notification when files are altered (either through filesystem polling, or a kernel notification mechanism). If Nautilus is built without FAM support, directories viewed with Nautilus will not remain in synch with the actual filesystem when they are altered by external processes. Particularly if you are a distributor please compile Nautilus with FAM support. FAM is available from http://oss.sgi.com/projects/fam/. A patch to add Linux Kernel 2.4 directory notify support to FAM (highly desirable) is available from http://people.redhat.com/alexl/files/"
-FAM_LIBS=
-AC_CHECK_LIB(fam, FAMOpen,
- [AC_CHECK_HEADERS(fam.h,
- [AC_DEFINE(HAVE_LIBFAM)
- FAM_LIBS="-lfam"],
- AC_MSG_WARN(*** FAM support will not be built (header files not found) $FAM_MISSING_WARNING ***))],
- AC_MSG_WARN(*** FAM support will not be built (FAM library not found) $FAM_MISSING_WARNING ***))
-AC_SUBST(FAM_LIBS)
-
-AC_LANG_RESTORE
-
-dnl ==========================================================================
-
dnl x86 checks (used by audio routines in music component)
_system_is_x86="no"
@@ -287,7 +268,7 @@ dnl core nautilus (must list bonobo-activation and libbonobo because idldir does
CORE_MODULES="eel-2.0 librsvg-2.0 bonobo-activation-2.0 libbonobo-2.0 libbonoboui-2.0 esound gnome-desktop-2.0 $EXTRA_CORE_MODULES"
CORE_CFLAGS="`$PKG_CONFIG --cflags $CORE_MODULES` $x_cflags"
AC_SUBST(CORE_CFLAGS)
-CORE_LIBS="`$PKG_CONFIG --libs $CORE_MODULES` $CDDA_LIBS $FAM_LIBS $LIBJPEG $x_libs"
+CORE_LIBS="`$PKG_CONFIG --libs $CORE_MODULES` $CDDA_LIBS $LIBJPEG $x_libs"
AC_SUBST(CORE_LIBS)
CORE_IDL_INCLUDES="`$PKG_CONFIG --variable=idldir $CORE_MODULES | $srcdir/add-include-prefix`"
AC_SUBST(CORE_IDL_INCLUDES)
diff --git a/libnautilus-private/nautilus-monitor.c b/libnautilus-private/nautilus-monitor.c
index 48787cf9d..b61e31462 100644
--- a/libnautilus-private/nautilus-monitor.c
+++ b/libnautilus-private/nautilus-monitor.c
@@ -21,210 +21,49 @@
Authors: Seth Nickell <seth@eazel.com>
Darin Adler <darin@bentspoon.com>
+ Alex Graveley <alex@ximian.com>
*/
#include <config.h>
#include "nautilus-monitor.h"
-
-#include <eel/eel-glib-extensions.h>
-
-#ifdef HAVE_LIBFAM
-
#include "nautilus-file-changes-queue.h"
+#include "nautilus-file-utilities.h"
#include "nautilus-volume-monitor.h"
-#include <fam.h>
-#include <gdk/gdk.h>
-#include <gmodule.h>
+
#include <libgnome/gnome-util.h>
#include <libgnomevfs/gnome-vfs-utils.h>
+#include <libgnomevfs/gnome-vfs-ops.h>
struct NautilusMonitor {
- FAMRequest request;
+ GnomeVFSMonitorHandle *handle;
};
-static gboolean got_connection;
-
-static gboolean process_fam_notifications (GIOChannel *channel,
- GIOCondition cond,
- gpointer callback_data);
-
-/* singleton object, instantiate and connect if it doesn't already exist */
-static FAMConnection *
-get_fam_connection (void)
-{
- static gboolean tried_connection;
- static FAMConnection connection;
- GIOChannel *ioc;
-
- /* Only try once. */
- if (tried_connection) {
- if (!got_connection) {
- return NULL;
- }
- } else {
- tried_connection = TRUE;
- if (FAMOpen2 (&connection, "Nautilus") != 0) {
- return NULL;
- }
-
- /* Make the main loop's select function watch the FAM
- * connection's file descriptor for us.
- */
- ioc = g_io_channel_unix_new (FAMCONNECTION_GETFD (&connection));
- g_io_add_watch (ioc, G_IO_IN | G_IO_HUP, process_fam_notifications, NULL);
- g_io_channel_unref (ioc);
-
- got_connection = TRUE;
- }
- return &connection;
-}
-
-static GHashTable *
-get_request_hash_table (void)
+gboolean
+nautilus_monitor_active (void)
{
- static GHashTable *table;
+ static gboolean tried_monitor = FALSE;
+ static gboolean monitor_success;
+ char *desktop_directory, *uri;
+ NautilusMonitor *monitor;
- if (table == NULL) {
- table = eel_g_hash_table_new_free_at_exit
- (NULL, NULL, "nautilus-monitor.c: FAM requests");
- }
- return table;
-}
+ if (tried_monitor == FALSE) {
+ desktop_directory = nautilus_get_desktop_directory ();
+ uri = gnome_vfs_get_uri_from_local_path (desktop_directory);
-static char *
-get_event_uri (const FAMEvent *event)
-{
- const char *base_path;
- char *path, *uri;
+ monitor = nautilus_monitor_directory (uri);
+ monitor_success = (monitor != NULL);
- /* FAM doesn't tell us when something is a full path and when
- * it's just partial so we have to look and see if it starts
- * with a /.
- */
- if (event->filename[0] == '/') {
- return gnome_vfs_get_uri_from_local_path (event->filename);
- }
+ if (monitor != NULL) {
+ nautilus_monitor_cancel (monitor);
+ }
- /* Look up the directory registry that was used for this file
- * notification and tack that on.
- */
- base_path = g_hash_table_lookup (get_request_hash_table (),
- GINT_TO_POINTER (FAMREQUEST_GETREQNUM (&event->fr)));
+ g_free (desktop_directory);
+ g_free (uri);
- /* base_path can be NULL if we've cancelled the monitor but still have
- * some change notifications in our queue. Just return NULL In that case.
- */
- if (base_path == NULL) {
- return NULL;
+ tried_monitor = TRUE;
}
- path = g_build_filename (base_path, event->filename, NULL);
- uri = gnome_vfs_get_uri_from_local_path (path);
- g_free (path);
- return uri;
-}
-
-static gboolean
-process_fam_notifications (GIOChannel *channel,
- GIOCondition cond,
- gpointer callback_data)
-{
- FAMConnection *connection;
- FAMEvent event;
- char *uri;
-
- connection = get_fam_connection ();
- g_return_val_if_fail (connection != NULL, FALSE);
-
- /* Process all the pending events right now. */
-
- while (FAMPending (connection)) {
- if (FAMNextEvent (connection, &event) != 1) {
- g_warning ("connection to FAM died");
- FAMClose (connection);
- got_connection = FALSE;
- return FALSE;
- }
-
- switch (event.code) {
- case FAMChanged:
- uri = get_event_uri (&event);
- if (uri == NULL) {
- break;
- }
- nautilus_file_changes_queue_file_changed (uri);
- g_free (uri);
- break;
-
- case FAMDeleted:
- uri = get_event_uri (&event);
- if (uri == NULL) {
- break;
- }
- nautilus_file_changes_queue_file_removed (uri);
- g_free (uri);
- break;
-
- case FAMCreated:
- uri = get_event_uri (&event);
- if (uri == NULL) {
- break;
- }
- nautilus_file_changes_queue_file_added (uri);
- g_free (uri);
- break;
-
- case FAMStartExecuting:
- /* Emitted when a file you are monitoring is
- * executed. This should work for both
- * binaries and shell scripts. Nautilus is not
- * doing anything with this yet.
- */
- break;
-
- case FAMStopExecuting:
- /* Emitted when a file you are monitoring
- * ceases execution. Nautilus is not doing
- * anything with this yet.
- */
- break;
-
- case FAMAcknowledge:
- /* Called in response to a successful
- * CancelMonitor. We don't need to do anything
- * with this information.
- */
- break;
-
- case FAMExists:
- /* Emitted when you start monitoring a
- * directory. It tells you what's in the
- * directory. Unhandled because Nautilus
- * already handles this by calling
- * gnome_vfs_directory_load, which gives us
- * more information than merely the file name.
- */
- break;
-
- case FAMEndExist:
- /* Emitted at the end of a FAMExists stream. */
- break;
-
- case FAMMoved:
- /* FAMMoved doesn't need to be handled because
- * FAM never seems to generate this event on
- * Linux systems (with or without kernel
- * support). Instead it generates a FAMDeleted
- * followed by a FAMCreated.
- */
- g_warning ("unexpected FAMMoved notification");
- break;
- }
- }
-
- nautilus_file_changes_consume_changes (TRUE);
-
- return TRUE;
+ return monitor_success;
}
static gboolean
@@ -234,130 +73,106 @@ path_is_on_readonly_volume (const char *path)
NautilusVolume *volume;
volume_monitor = nautilus_volume_monitor_get ();
- volume = nautilus_volume_monitor_get_volume_for_path (volume_monitor, path);
- return (volume != NULL) && nautilus_volume_is_read_only (volume);
+ volume = nautilus_volume_monitor_get_volume_for_path (volume_monitor,
+ path);
+ if (volume != NULL) {
+ return nautilus_volume_is_read_only (volume);
+ } else {
+ return FALSE;
+ }
}
-#endif /* HAVE_LIBFAM */
+static gboolean call_consume_changes_idle_id = 0;
-gboolean
-nautilus_monitor_active (void)
+static gboolean
+call_consume_changes_idle_cb (gpointer not_used)
{
-#ifndef HAVE_LIBFAM
+ nautilus_file_changes_consume_changes (TRUE);
+ call_consume_changes_idle_id = 0;
return FALSE;
-#else
- return get_fam_connection () != NULL;
-#endif
}
-NautilusMonitor *
-nautilus_monitor_file (const char *uri)
+static void
+monitor_notify_cb (GnomeVFSMonitorHandle *handle,
+ const gchar *monitor_uri,
+ const gchar *info_uri,
+ GnomeVFSMonitorEventType event_type,
+ gpointer user_data)
{
-#ifndef HAVE_LIBFAM
- return NULL;
-#else
- FAMConnection *connection;
- char *path;
- NautilusMonitor *monitor;
+ switch (event_type) {
+ case GNOME_VFS_MONITOR_EVENT_CHANGED:
+ nautilus_file_changes_queue_file_changed (info_uri);
+ break;
+ case GNOME_VFS_MONITOR_EVENT_DELETED:
+ nautilus_file_changes_queue_file_removed (info_uri);
+ break;
+ case GNOME_VFS_MONITOR_EVENT_CREATED:
+ nautilus_file_changes_queue_file_added (info_uri);
+ break;
+
+ /* None of the following are supported yet */
+ case GNOME_VFS_MONITOR_EVENT_STARTEXECUTING:
+ case GNOME_VFS_MONITOR_EVENT_STOPEXECUTING:
+ case GNOME_VFS_MONITOR_EVENT_METADATA_CHANGED:
+ break;
+ }
- connection = get_fam_connection ();
- if (connection == NULL) {
- return NULL;
+ if (call_consume_changes_idle_id == 0) {
+ call_consume_changes_idle_id =
+ g_idle_add (call_consume_changes_idle_cb, NULL);
}
+}
+
+static NautilusMonitor *
+monitor_add_internal (const char *uri, gboolean is_directory)
+{
+ gchar *path;
+ NautilusMonitor *ret;
+ GnomeVFSResult result;
path = gnome_vfs_get_local_path_from_uri (uri);
- if (path == NULL) {
+ if (path != NULL &&
+ path_is_on_readonly_volume (path) == FALSE) {
+ g_free (path);
return NULL;
}
+ g_free (path);
- /* Check to see if the file system is readonly. If so, don't monitor --
- * there is no point, and we'll just keep the file system busy for
- * no reason, preventing unmounting
- */
- if (path_is_on_readonly_volume (path)) {
- g_free (path);
+ ret = g_new0 (NautilusMonitor, 1);
+
+ result = gnome_vfs_monitor_add (&ret->handle,
+ uri,
+ is_directory == TRUE ?
+ GNOME_VFS_MONITOR_DIRECTORY :
+ GNOME_VFS_MONITOR_FILE,
+ monitor_notify_cb,
+ NULL);
+ if (result != GNOME_VFS_OK) {
+ g_free (ret);
return NULL;
}
-
- monitor = g_new0 (NautilusMonitor, 1);
- FAMMonitorFile (connection, path, &monitor->request, NULL);
- g_free (path);
-
- return monitor;
-#endif
+ return ret;
}
-
-
NautilusMonitor *
nautilus_monitor_directory (const char *uri)
{
-#ifndef HAVE_LIBFAM
- return NULL;
-#else
- FAMConnection *connection;
- char *path;
- NautilusMonitor *monitor;
-
- connection = get_fam_connection ();
- if (connection == NULL) {
- return NULL;
- }
-
- path = gnome_vfs_get_local_path_from_uri (uri);
- if (path == NULL) {
- return NULL;
- }
-
- /* Check to see if the file system is readonly. If so, don't monitor --
- * there is no point, and we'll just keep the file system busy for
- * no reason, preventing unmounting
- */
- if (path_is_on_readonly_volume (path)) {
- g_free (path);
- return NULL;
- }
-
- monitor = g_new0 (NautilusMonitor, 1);
- FAMMonitorDirectory (connection, path, &monitor->request, NULL);
-
- g_assert (g_hash_table_lookup (get_request_hash_table (),
- GINT_TO_POINTER (FAMREQUEST_GETREQNUM (&monitor->request))) == NULL);
-
- g_hash_table_insert (get_request_hash_table (),
- GINT_TO_POINTER (FAMREQUEST_GETREQNUM (&monitor->request)),
- path);
+ return monitor_add_internal (uri, TRUE);
+}
- return monitor;
-#endif
+NautilusMonitor *
+nautilus_monitor_file (const char *uri)
+{
+ return monitor_add_internal (uri, FALSE);
}
-void
+void
nautilus_monitor_cancel (NautilusMonitor *monitor)
-{
-#ifndef HAVE_LIBFAM
- g_return_if_fail (monitor == NULL);
-#else
- FAMConnection *connection;
- int reqnum;
- char *path;
-
- if (monitor == NULL) {
- return;
+{
+ if (monitor->handle != NULL) {
+ gnome_vfs_monitor_cancel (monitor->handle);
}
- reqnum = FAMREQUEST_GETREQNUM (&monitor->request);
- path = g_hash_table_lookup (get_request_hash_table (),
- GINT_TO_POINTER (reqnum));
- g_hash_table_remove (get_request_hash_table (),
- GINT_TO_POINTER (reqnum));
- g_free (path);
-
- connection = get_fam_connection ();
- g_return_if_fail (connection != NULL);
-
- FAMCancelMonitor (connection, &monitor->request);
g_free (monitor);
-#endif
}