1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
2
3 caja-monitor.c: file and directory change monitoring for caja
4
5 Copyright (C) 2000, 2001 Eazel, Inc.
6
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU General Public
18 License along with this program; if not, write to the
19 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20 Boston, MA 02110-1301, USA.
21
22 Authors: Seth Nickell <seth@eazel.com>
23 Darin Adler <darin@bentspoon.com>
24 Alex Graveley <alex@ximian.com>
25 */
26
27 #include <config.h>
28 #include "caja-monitor.h"
29 #include "caja-file-changes-queue.h"
30 #include "caja-file-utilities.h"
31
32 #include <gio/gio.h>
33
34 struct CajaMonitor
35 {
36 GFileMonitor *monitor;
37 GVolumeMonitor *volume_monitor;
38 GMount *mount;
39 GFile *location;
40 };
41
42 gboolean
caja_monitor_active(void)43 caja_monitor_active (void)
44 {
45 static gboolean tried_monitor = FALSE;
46 static gboolean monitor_success;
47 GFileMonitor *dir_monitor;
48
49 if (tried_monitor == FALSE)
50 {
51 GFile *file;
52
53 file = g_file_new_for_path (g_get_home_dir ());
54 dir_monitor = g_file_monitor_directory (file, G_FILE_MONITOR_NONE, NULL, NULL);
55 g_object_unref (file);
56
57 monitor_success = (dir_monitor != NULL);
58 if (dir_monitor)
59 {
60 g_object_unref (dir_monitor);
61 }
62
63 tried_monitor = TRUE;
64 }
65
66 return monitor_success;
67 }
68
69 static gboolean call_consume_changes_idle_id = 0;
70
71 static gboolean
call_consume_changes_idle_cb(gpointer not_used)72 call_consume_changes_idle_cb (gpointer not_used)
73 {
74 caja_file_changes_consume_changes (TRUE);
75 call_consume_changes_idle_id = 0;
76 return FALSE;
77 }
78
79 static void
schedule_call_consume_changes(void)80 schedule_call_consume_changes (void)
81 {
82 if (call_consume_changes_idle_id == 0) {
83 call_consume_changes_idle_id =
84 g_idle_add (call_consume_changes_idle_cb, NULL);
85 }
86 }
87
88 static void
mount_removed(GVolumeMonitor * volume_monitor,GMount * mount,gpointer user_data)89 mount_removed (GVolumeMonitor *volume_monitor,
90 GMount *mount,
91 gpointer user_data)
92 {
93 CajaMonitor *monitor = user_data;
94 if (mount == monitor->mount) {
95 caja_file_changes_queue_file_removed (monitor->location);
96 schedule_call_consume_changes ();
97 }
98 }
99
100 static void
dir_changed(GFileMonitor * monitor,GFile * child,GFile * other_file,GFileMonitorEvent event_type,gpointer user_data)101 dir_changed (GFileMonitor* monitor,
102 GFile *child,
103 GFile *other_file,
104 GFileMonitorEvent event_type,
105 gpointer user_data)
106 {
107 char *uri, *to_uri;
108
109 uri = g_file_get_uri (child);
110 to_uri = NULL;
111 if (other_file)
112 {
113 to_uri = g_file_get_uri (other_file);
114 }
115
116 switch (event_type)
117 {
118 default:
119 case G_FILE_MONITOR_EVENT_CHANGED:
120 /* ignore */
121 break;
122 case G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED:
123 case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
124 caja_file_changes_queue_file_changed (child);
125 break;
126 case G_FILE_MONITOR_EVENT_DELETED:
127 caja_file_changes_queue_file_removed (child);
128 break;
129 case G_FILE_MONITOR_EVENT_CREATED:
130 caja_file_changes_queue_file_added (child);
131 break;
132
133 case G_FILE_MONITOR_EVENT_PRE_UNMOUNT:
134 /* TODO: Do something */
135 break;
136 case G_FILE_MONITOR_EVENT_UNMOUNTED:
137 /* TODO: Do something */
138 break;
139 }
140
141 g_free (uri);
142 g_free (to_uri);
143 schedule_call_consume_changes ();
144 }
145
146 CajaMonitor *
caja_monitor_directory(GFile * location)147 caja_monitor_directory (GFile *location)
148 {
149 GFileMonitor *dir_monitor;
150 CajaMonitor *ret;
151
152 ret = g_new0 (CajaMonitor, 1);
153 dir_monitor = g_file_monitor_directory (location, G_FILE_MONITOR_WATCH_MOUNTS, NULL, NULL);
154
155 if (dir_monitor != NULL) {
156 ret->monitor = dir_monitor;
157 }
158 /*This caused a crash on umounting remote shares
159 else if (!g_file_is_native (location)) {
160 ret->mount = caja_get_mounted_mount_for_root (location);
161 ret->location = g_object_ref (location);
162 ret->volume_monitor = g_volume_monitor_get ();
163 }
164 */
165 if (ret->monitor != NULL) {
166 g_signal_connect (ret->monitor, "changed",
167 G_CALLBACK (dir_changed), ret);
168 }
169
170 if (ret->monitor) {
171 g_signal_connect (ret->monitor, "changed", (GCallback)dir_changed, ret);
172 }
173
174 if (ret->volume_monitor != NULL) {
175 g_signal_connect (ret->volume_monitor, "mount-removed",
176 G_CALLBACK (mount_removed), ret);
177 }
178
179 /* We return a monitor even on failure, so we can avoid later trying again */
180 return ret;
181 }
182
183 void
caja_monitor_cancel(CajaMonitor * monitor)184 caja_monitor_cancel (CajaMonitor *monitor)
185 {
186 if (monitor->monitor != NULL)
187 {
188 g_signal_handlers_disconnect_by_func (monitor->monitor, dir_changed, monitor);
189 g_file_monitor_cancel (monitor->monitor);
190 g_object_unref (monitor->monitor);
191 }
192
193 if (monitor->volume_monitor != NULL) {
194 g_signal_handlers_disconnect_by_func (monitor->volume_monitor, mount_removed, monitor);
195 g_object_unref (monitor->volume_monitor);
196 }
197
198 g_clear_object (&monitor->location);
199 g_clear_object (&monitor->mount);
200 g_free (monitor);
201 }
202