mirror of
https://gitlab.gnome.org/GNOME/nautilus
synced 2024-11-05 16:04:31 +00:00
ede19226c5
2001-09-05 Alex Larsson <alexl@redhat.com> Merge some stuff from the redhat-outstanding-patches branch * eazel-logos/default.xml: * icons/default.xml: don't hardcode the title, title info, and shadow colors; this prevented the auto-color-selection stuff in nautilus-sidebar-title.c from working properly. And the hardcoded values were the same thing the autoselector would have chosen anyhow. * libnautilus-private/nautilus-monitor.c: Don't monitor files on read only volumes, they never change, and will keep cdroms from being unmounted because fam has open file descriptors on them. * libnautilus-private/nautilus-thumbnails.c: Always look for local thumbnails first. * libnautilus-private/nautilus-volume-monitor.[ch]: Add nautilus_volume_is_read_only() and nautilus_volume_monitor_get_volume_for_path() * src/nautilus-desktop-window.c: (set_wmspec_desktop_hint): function to set _NET_WM_WINDOW_TYPE, to avoid confusing kwin so badly, and also to go ahead and support the Window Manager Hints Of The Future. (set_gdk_window_background): only set root background to a pixel if we retrieved a pixel property (map): Set background of our child widgets in addition to our own background. This gets rid of the last of the ugliness during Nautilus startup, I believe. * src/file-manager/fm-icon-view.c: Don't read GMC position meta data -- it is never right for nautilus, due to different size icons, additional icons, different placement policies, so falling back to normal automatic placement works better.
357 lines
8.9 KiB
C
357 lines
8.9 KiB
C
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
|
|
|
|
nautilus-monitor.c: file and directory change monitoring for nautilus
|
|
|
|
Copyright (C) 2000, 2001 Eazel, Inc.
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License as
|
|
published by the Free Software Foundation; either version 2 of the
|
|
License, or (at your option) any later version.
|
|
|
|
This program 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
|
|
General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public
|
|
License along with this program; if not, write to the
|
|
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
Boston, MA 02111-1307, USA.
|
|
|
|
Authors: Seth Nickell <seth@eazel.com>
|
|
Darin Adler <darin@eazel.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-volume-monitor.h"
|
|
#include <fam.h>
|
|
#include <gdk/gdk.h>
|
|
#include <gmodule.h>
|
|
#include <libgnome/gnome-defs.h>
|
|
#include <libgnome/gnome-util.h>
|
|
#include <libgnomevfs/gnome-vfs-utils.h>
|
|
|
|
struct NautilusMonitor {
|
|
FAMRequest request;
|
|
};
|
|
|
|
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)
|
|
{
|
|
static GHashTable *table;
|
|
|
|
if (table == NULL) {
|
|
table = eel_g_hash_table_new_free_at_exit
|
|
(NULL, NULL, "nautilus-monitor.c: FAM requests");
|
|
}
|
|
return table;
|
|
}
|
|
|
|
static char *
|
|
get_event_uri (const FAMEvent *event)
|
|
{
|
|
const char *base_path;
|
|
char *path, *uri;
|
|
|
|
/* 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);
|
|
}
|
|
|
|
/* 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_return_val_if_fail (base_path != NULL, NULL);
|
|
path = g_concat_dir_and_file (base_path, event->filename);
|
|
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 (w/ or w/o IMON). Instead it
|
|
* generates a FAMDeleted followed by a
|
|
* FAMCreated.
|
|
*/
|
|
g_warning ("unexpected FAMMoved notification");
|
|
break;
|
|
}
|
|
}
|
|
|
|
nautilus_file_changes_consume_changes (TRUE);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
#endif /* HAVE_LIBFAM */
|
|
|
|
gboolean
|
|
nautilus_monitor_active (void)
|
|
{
|
|
#ifndef HAVE_LIBFAM
|
|
return FALSE;
|
|
#else
|
|
return get_fam_connection () != NULL;
|
|
#endif
|
|
}
|
|
|
|
static gboolean
|
|
path_is_on_readonly_volume (const char *path)
|
|
{
|
|
NautilusVolumeMonitor *volume_monitor;
|
|
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);
|
|
}
|
|
|
|
NautilusMonitor *
|
|
nautilus_monitor_file (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);
|
|
FAMMonitorFile (connection, path, &monitor->request, NULL);
|
|
|
|
g_free (path);
|
|
|
|
return monitor;
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
#endif
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
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
|
|
}
|