[Xfce4-commits] <xfdesktop:xfce-4.8> Handle volume changes in a timeout (bug #7025).
Jannis Pohlmann
noreply at xfce.org
Sat Jan 29 18:22:01 CET 2011
Updating branch refs/heads/xfce-4.8
to e8bc0f168577c84e5576ea2702efda2e0b83311a (commit)
from 45916b4e00a878fcc6f530f30932220b43a2e7a9 (commit)
commit e8bc0f168577c84e5576ea2702efda2e0b83311a
Author: Jannis Pohlmann <jannis at xfce.org>
Date: Tue Jan 25 02:21:40 2011 +0100
Handle volume changes in a timeout (bug #7025).
When the "volume-changed" signal of GVolumeMonitor or the "changed"
signal of GVolume are emitted after a volume has been mounted, then for
some reason the affected GVolume still has no valid GMount. Same happens
when unmounting: the GVolume still has a valid GMount.
This commit works around this by checking for a change from valid to
invalid GMount or from invalid to valid GMount in a timeout that is
called at most 5 times until it gives up. When a change is detected, the
corresponding XfdesktopVolumeIcon is updated.
I hope this is a suitable workaround for most machines/drives. The
underlying issue seems to be in GIO or GVfs. It might be worth finding
the root cause.
NEWS | 1 +
src/xfdesktop-volume-icon.c | 148 ++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 146 insertions(+), 3 deletions(-)
diff --git a/NEWS b/NEWS
index 7585786..e7ecf33 100644
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,7 @@ Xfdesktop 4.x.y
* Support absolute icon paths in desktop files (bug #7160).
Patch by xaizek at gmail.com.
* Scroll to the selected background in the settings (bug #7087).
+ * Handle volume changes in a timeout (bug #7025).
Xfdesktop 4.8.0
diff --git a/src/xfdesktop-volume-icon.c b/src/xfdesktop-volume-icon.c
index 85a44dc..01a5570 100644
--- a/src/xfdesktop-volume-icon.c
+++ b/src/xfdesktop-volume-icon.c
@@ -1,9 +1,9 @@
/*
* xfdesktop - xfce4's desktop manager
*
- * Copyright(c) 2006 Brian Tarricone, <bjt23 at cornell.edu>
- * Copyright(c) 2006 Benedikt Meurer, <benny at xfce.org>
- * Copyright(c) 2010 Jannis Pohlmann, <jannis at xfce.org>
+ * Copyright(c) 2006 Brian Tarricone, <bjt23 at cornell.edu>
+ * Copyright(c) 2006 Benedikt Meurer, <benny at xfce.org>
+ * Copyright(c) 2010-2011 Jannis Pohlmann, <jannis at xfce.org>
*
* 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
@@ -67,6 +67,9 @@ struct _XfdesktopVolumeIconPrivate
GFileInfo *filesystem_info;
GFile *file;
GdkScreen *gscreen;
+
+ guint changed_timeout_id;
+ guint changed_timeout_count;
};
static void xfdesktop_volume_icon_finalize(GObject *obj);
@@ -89,6 +92,9 @@ static GFile *xfdesktop_volume_icon_peek_file(XfdesktopFileIcon *icon);
static void xfdesktop_volume_icon_update_file_info(XfdesktopFileIcon *icon,
GFileInfo *info);
static gboolean xfdesktop_volume_icon_activated(XfdesktopIcon *icon);
+static gboolean volume_icon_changed_timeout(XfdesktopVolumeIcon *icon);
+static void xfdesktop_volume_icon_changed(GVolume *volume,
+ XfdesktopVolumeIcon *volume_icon);
#ifdef HAVE_THUNARX
static void xfdesktop_volume_icon_tfi_init(ThunarxFileInfoIface *iface);
@@ -156,6 +162,10 @@ xfdesktop_volume_icon_finalize(GObject *obj)
{
XfdesktopVolumeIcon *icon = XFDESKTOP_VOLUME_ICON(obj);
GtkIconTheme *itheme = gtk_icon_theme_get_for_screen(icon->priv->gscreen);
+
+ /* remove pending change timeouts */
+ if(icon->priv->changed_timeout_id > 0)
+ g_source_remove(icon->priv->changed_timeout_id);
g_signal_handlers_disconnect_by_func(G_OBJECT(itheme),
G_CALLBACK(xfdesktop_volume_icon_invalidate_pixbuf),
@@ -800,6 +810,134 @@ xfdesktop_volume_icon_activated(XfdesktopIcon *icon_p)
}
}
+static gboolean
+volume_icon_changed_timeout(XfdesktopVolumeIcon *volume_icon)
+{
+ GMount *mount;
+ gboolean mounted_before = FALSE;
+ gboolean mounted_after = FALSE;
+
+ g_return_val_if_fail(XFDESKTOP_IS_VOLUME_ICON(volume_icon), FALSE);
+
+ DBG("TIMEOUT");
+
+ /* reset the icon's mount point information */
+ if(volume_icon->priv->file) {
+ g_object_unref(volume_icon->priv->file);
+ volume_icon->priv->file = NULL;
+
+ /* apparently the volume was mounted before, otherwise
+ * we wouldn't have had a mount point for it */
+ mounted_before = TRUE;
+ }
+ if(volume_icon->priv->file_info) {
+ g_object_unref(volume_icon->priv->file_info);
+ volume_icon->priv->file_info = NULL;
+ }
+ if(volume_icon->priv->filesystem_info) {
+ g_object_unref(volume_icon->priv->filesystem_info);
+ volume_icon->priv->filesystem_info = NULL;
+ }
+
+ /* check if we have a valid mount now */
+ mount = g_volume_get_mount(volume_icon->priv->volume);
+ if(mount) {
+ /* load mount point information */
+ volume_icon->priv->file = g_mount_get_root(mount);
+ volume_icon->priv->file_info =
+ g_file_query_info(volume_icon->priv->file,
+ XFDESKTOP_FILE_INFO_NAMESPACE,
+ G_FILE_QUERY_INFO_NONE,
+ NULL, NULL);
+ volume_icon->priv->filesystem_info =
+ g_file_query_filesystem_info(volume_icon->priv->file,
+ XFDESKTOP_FILESYSTEM_INFO_NAMESPACE,
+ NULL, NULL);
+
+ /* release the mount itself */
+ g_object_unref(mount);
+
+ /* the device is mounted now (we have a mount point for it) */
+ mounted_after = TRUE;
+ }
+
+ DBG("MOUNTED BEFORE: %d, MOUNTED AFTER: %d", mounted_before, mounted_after);
+
+ if(mounted_before != mounted_after) {
+ /* invalidate the tooltip */
+ if(volume_icon->priv->tooltip) {
+ g_free(volume_icon->priv->tooltip);
+ volume_icon->priv->tooltip = NULL;
+ }
+
+ /* not really easy to check if this changed or not, so just invalidate it */
+ xfdesktop_volume_icon_invalidate_pixbuf(volume_icon);
+ xfdesktop_icon_pixbuf_changed(XFDESKTOP_ICON(volume_icon));
+
+ /* finalize the timeout source */
+ volume_icon->priv->changed_timeout_id = 0;
+ return FALSE;
+ } else {
+ /* increment the timeout counter */
+ volume_icon->priv->changed_timeout_count += 1;
+
+ if(volume_icon->priv->changed_timeout_count >= 5) {
+ /* finalize the timeout source */
+ volume_icon->priv->changed_timeout_id = 0;
+ return FALSE;
+ } else {
+ DBG("TRY AGAIN");
+ return TRUE;
+ }
+ }
+}
+
+static void
+xfdesktop_volume_icon_changed(GVolume *volume,
+ XfdesktopVolumeIcon *volume_icon)
+{
+ gboolean is_present;
+
+ g_return_if_fail(G_IS_VOLUME(volume));
+ g_return_if_fail(XFDESKTOP_IS_VOLUME_ICON(volume_icon));
+
+ DBG("VOLUME CHANGED");
+
+ is_present = xfdesktop_file_utils_volume_is_present(volume);
+ if(!is_present) {
+ /* don't do anything because the icon will be removed from
+ * the file icon manager anyway */
+ return;
+ }
+
+ DBG("VOLUME STILL PRESENT");
+
+ /**
+ * NOTE: We use a timeout here to check if the volume is
+ * now mounted (or has been unmounted). This timeout seems
+ * to be needed because when the "changed" signal is emitted,
+ * the GMount is always NULL. In a 500ms timeout we check
+ * at most 5 times for a valid mount until we give up. This
+ * hopefully is a suitable workaround for most machines and
+ * drives.
+ */
+
+ /* abort an existing timeout, we may have to run it a few times
+ * once again for the new event */
+ if(volume_icon->priv->changed_timeout_id > 0) {
+ g_source_remove(volume_icon->priv->changed_timeout_id);
+ volume_icon->priv->changed_timeout_id = 0;
+ }
+
+ /* reset timeout information and start a timeout */
+ volume_icon->priv->changed_timeout_count = 0;
+ volume_icon->priv->changed_timeout_id =
+ g_timeout_add_full(G_PRIORITY_LOW, 500,
+ (GSourceFunc) volume_icon_changed_timeout,
+ g_object_ref(volume_icon),
+ g_object_unref);
+}
+
XfdesktopVolumeIcon *
xfdesktop_volume_icon_new(GVolume *volume,
GdkScreen *screen)
@@ -825,6 +963,10 @@ xfdesktop_volume_icon_new(GVolume *volume,
NULL, NULL);
g_object_unref(mount);
}
+
+ g_signal_connect(volume, "changed",
+ G_CALLBACK(xfdesktop_volume_icon_changed),
+ volume_icon);
return volume_icon;
}
More information about the Xfce4-commits
mailing list