From 8fff655552209fd181f9608d02d0f72660b10768 Mon Sep 17 00:00:00 2001 From: lukefromdc Date: Mon, 15 Oct 2018 22:20:03 -0400 Subject: monitor: watch for removal of non-native mounts on GVolumeMonitor Fix https://github.com/mate-desktop/caja/issues/1066 "Caja caches folders from usb drives/disk" Nowadays, we rely on G_FILE_MONITOR_EVENT_UNMOUNTED to be emitted when a mount disappears, since we already monitor the directory, in order to switch the view to a different location. Since non-native mounts very likely won't have file monitoring though, we're not going to receive such events in that case, and fail to redirect the view as a consequence. This patch fixes it by listening to the mount-removed signal on GVolumeMonitor when a monitor is requested for a non-native mount, and emulating a file removal in that case. Backport Nautilus commit gitlab.gnome.org/GNOME/nautilus/commit/3891241ba760c59d284b7579dbd340651c8d4d29 note that caja_get_mounted_mount_for_root had to be added, while the equivalent Nautilus function was from a prior commit --- libcaja-private/caja-file-utilities.c | 42 +++++++++++++++++++++++ libcaja-private/caja-file-utilities.h | 1 + libcaja-private/caja-monitor.c | 63 +++++++++++++++++++++++++++++------ 3 files changed, 96 insertions(+), 10 deletions(-) diff --git a/libcaja-private/caja-file-utilities.c b/libcaja-private/caja-file-utilities.c index 237f85d7..46f90b0a 100644 --- a/libcaja-private/caja-file-utilities.c +++ b/libcaja-private/caja-file-utilities.c @@ -756,6 +756,48 @@ caja_is_desktop_directory (GFile *dir) return g_file_equal (dir, desktop_dir); } +GMount * +caja_get_mounted_mount_for_root (GFile *location) +{ + GVolumeMonitor *volume_monitor; + GList *mounts; + GList *l; + GMount *mount; + GMount *result = NULL; + GFile *root = NULL; + GFile *default_location = NULL; + + volume_monitor = g_volume_monitor_get (); + mounts = g_volume_monitor_get_mounts (volume_monitor); + + for (l = mounts; l != NULL; l = l->next) { + mount = l->data; + + if (g_mount_is_shadowed (mount)) { + continue; + } + + root = g_mount_get_root (mount); + if (g_file_equal (location, root)) { + result = g_object_ref (mount); + break; + } + + default_location = g_mount_get_default_location (mount); + if (!g_file_equal (default_location, root) && + g_file_equal (location, default_location)) { + result = g_object_ref (mount); + break; + } + } + + g_clear_object (&root); + g_clear_object (&default_location); + g_list_free_full (mounts, g_object_unref); + + return result; +} + /** * caja_get_pixmap_directory * diff --git a/libcaja-private/caja-file-utilities.h b/libcaja-private/caja-file-utilities.h index 370cec02..2306601f 100644 --- a/libcaja-private/caja-file-utilities.h +++ b/libcaja-private/caja-file-utilities.h @@ -47,6 +47,7 @@ gboolean caja_is_desktop_directory (GFile *dir); gboolean caja_is_home_directory (GFile *dir); gboolean caja_is_home_directory_file (GFile *dir, const char *filename); +GMount * caja_get_mounted_mount_for_root (GFile *location); gboolean caja_is_in_system_dir (GFile *location); char * caja_get_pixmap_directory (void); diff --git a/libcaja-private/caja-monitor.c b/libcaja-private/caja-monitor.c index 0434dfe2..73d18f36 100644 --- a/libcaja-private/caja-monitor.c +++ b/libcaja-private/caja-monitor.c @@ -34,6 +34,9 @@ struct CajaMonitor { GFileMonitor *monitor; + GVolumeMonitor *volume_monitor; + GMount *mount; + GFile *location; }; gboolean @@ -72,6 +75,27 @@ call_consume_changes_idle_cb (gpointer not_used) return FALSE; } +static void +schedule_call_consume_changes (void) +{ + if (call_consume_changes_idle_id == 0) { + call_consume_changes_idle_id = + g_idle_add (call_consume_changes_idle_cb, NULL); + } +} + +static void +mount_removed (GVolumeMonitor *volume_monitor, + GMount *mount, + gpointer user_data) +{ + CajaMonitor *monitor = user_data; + if (mount == monitor->mount) { + caja_file_changes_queue_file_removed (monitor->location); + schedule_call_consume_changes (); + } +} + static void dir_changed (GFileMonitor* monitor, GFile *child, @@ -115,12 +139,7 @@ dir_changed (GFileMonitor* monitor, g_free (uri); g_free (to_uri); - - if (call_consume_changes_idle_id == 0) - { - call_consume_changes_idle_id = - g_idle_add (call_consume_changes_idle_cb, NULL); - } + schedule_call_consume_changes (); } CajaMonitor * @@ -129,16 +148,33 @@ caja_monitor_directory (GFile *location) GFileMonitor *dir_monitor; CajaMonitor *ret; + ret = g_new0 (CajaMonitor, 1); dir_monitor = g_file_monitor_directory (location, G_FILE_MONITOR_WATCH_MOUNTS, NULL, NULL); - ret = g_new0 (CajaMonitor, 1); - ret->monitor = dir_monitor; + if (dir_monitor != NULL) { + ret->monitor = dir_monitor; + } - if (ret->monitor) - { + else if (!g_file_is_native (location)) { + ret->mount = caja_get_mounted_mount_for_root (location); + ret->location = g_object_ref (location); + ret->volume_monitor = g_volume_monitor_get (); + } + + if (ret->monitor != NULL) { + g_signal_connect (ret->monitor, "changed", + G_CALLBACK (dir_changed), ret); + } + + if (ret->monitor) { g_signal_connect (ret->monitor, "changed", (GCallback)dir_changed, ret); } + if (ret->volume_monitor != NULL) { + g_signal_connect (ret->volume_monitor, "mount-removed", + G_CALLBACK (mount_removed), ret); + } + /* We return a monitor even on failure, so we can avoid later trying again */ return ret; } @@ -153,5 +189,12 @@ caja_monitor_cancel (CajaMonitor *monitor) g_object_unref (monitor->monitor); } + if (monitor->volume_monitor != NULL) { + g_signal_handlers_disconnect_by_func (monitor->volume_monitor, mount_removed, monitor); + g_object_unref (monitor->volume_monitor); + } + + g_clear_object (&monitor->location); + g_clear_object (&monitor->mount); g_free (monitor); } -- cgit v1.2.1