[Xfce4-commits] <xfdesktop:master> Merge branch 'eric/settings-changes'

Eric Koegel noreply at xfce.org
Sun Oct 27 19:42:11 CET 2013


Updating branch refs/heads/master
         to 3deb28c2b6f26951a556b1e46d69591c8f6c6299 (commit)
       from 984397d48d9a13215c804b0b283375706df62916 (commit)

commit 3deb28c2b6f26951a556b1e46d69591c8f6c6299
Merge: 984397d f6a34c5
Author: Eric Koegel <eric.koegel at gmail.com>
Date:   Sun Oct 27 21:40:04 2013 +0300

    Merge branch 'eric/settings-changes'

commit f6a34c5144f05eaf8327eca02da724353c542dff
Author: Eric Koegel <eric.koegel at gmail.com>
Date:   Sun Oct 27 10:59:48 2013 +0300

    Fix memory leaks in the settings app

commit ee9c70df22b26648ec734e84181f4bf27a892aec
Author: Eric Koegel <eric.koegel at gmail.com>
Date:   Sun Oct 27 10:38:54 2013 +0300

    Correctly display settings defaults
    
    When changing workspaces or monitors in the settings app, make sure
    we fall back to xfdesktop's defaults when nothing else has been
    configured.

commit 2f9278f47973b337f52619afece20cf498664fd6
Author: Eric Koegel <eric.koegel at gmail.com>
Date:   Sun Oct 27 09:29:43 2013 +0300

    Fix some memory leaks

commit 715985a0cfdcabe4eacc391c8f37690d343351e7
Author: Eric Koegel <eric.koegel at gmail.com>
Date:   Tue Oct 22 21:08:23 2013 +0300

    Include the chronological option in the combobox

commit 751d6e29c1ad3e02d7fdaaf873ff3c3285cc568a
Author: Eric Koegel <eric.koegel at gmail.com>
Date:   Mon Oct 21 11:39:03 2013 +0300

    Allow the font size to go to 0.
    
    Allow the user to set the font size to 0, at which point no icon
    label will be drawn.

commit 7b305eb5092ce88c32e019d6479903d630b9ae86
Author: Eric Koegel <eric.koegel at gmail.com>
Date:   Mon Oct 21 11:22:16 2013 +0300

    Tooltip options in xfdesktop-settings
    
    There's now an option to toggle the display of tooltips on the
    desktop as well as a spinbox to choose the preview image size.
    The tooltip style is still present and if the user doesn't change
    the tooltip size then it will fallback to the style setting, and
    then finally default to the DEFAULT_TOOLTIP_SIZE.

commit d12988225513fff7c219df973dd11e18a4670a27
Author: Eric Koegel <eric.koegel at gmail.com>
Date:   Mon Oct 21 09:11:46 2013 +0300

    Add a chronological backdrop cycle option
    
    When cycling backdrops sequentially with a period of hourly, setting
    this option causes xfdesktop to map files in the selected directory
    to hours of the day. Fewer images in the directory than hours in the
    day are handled by repeating images to scale them over the time range.
    That means there will be at most 24 images displayed showing the first
    image from midnight to one, the second from one until two o'clock,
    etc. If there were 6 images in the directory then every image would
    be displayed for 4 hour time intervals before advancing. If there's
    more images in the folder than hours then they won't be shown.
    The entire point is that the user can have darker backdrops shown at
    night or do other fancy time of day image selections (i.e. one image
    in the morning, one in the afternoon, one in the evening, etc).

commit 8ee9256cf6459ee827d8a98e09fa51e0ca7e2a30
Author: Eric Koegel <eric.koegel at gmail.com>
Date:   Sat Oct 19 21:20:43 2013 +0300

    Additonal backdrop cycle options
    
    Xfdesktop can now change the backdrop every x seconds, minutes,
    or hours. It can also change every hour on the hour, or every day,
    or just during start up.

commit c460b0acb86791eb7ee9d954fae505589b88a68a
Author: Eric Koegel <eric.koegel at gmail.com>
Date:   Tue Oct 15 19:25:30 2013 +0300

    More removable device icon types (Bug 4056)
    
    In xfdesktop-settings the removable devices option now has an
    expander allowing the user to show network shares, devices, or
    unknown/other volumes (such as mtp devices).

 common/xfdesktop-common.c                          |  135 ------
 common/xfdesktop-common.h                          |   12 +-
 common/xfdesktop-thumbnailer.c                     |   38 +-
 settings/main.c                                    |  194 +++++++--
 .../xfdesktop-settings-appearance-frame-ui.glade   |   35 +-
 settings/xfdesktop-settings-ui.glade               |   49 ++-
 src/xfce-backdrop.c                                |  450 +++++++++++++++++++-
 src/xfce-backdrop.h                                |   17 +
 src/xfce-desktop.c                                 |   37 +-
 src/xfce-workspace.c                               |   75 +++-
 src/xfdesktop-file-icon-manager.c                  |  235 ++++++----
 src/xfdesktop-file-icon-manager.h                  |   13 -
 src/xfdesktop-file-utils.c                         |  131 ------
 src/xfdesktop-file-utils.h                         |    3 -
 src/xfdesktop-icon-view.c                          |  113 ++++-
 src/xfdesktop-volume-icon.c                        |   11 -
 16 files changed, 1046 insertions(+), 502 deletions(-)

diff --git a/common/xfdesktop-common.c b/common/xfdesktop-common.c
index 6d5546d..2011e6c 100644
--- a/common/xfdesktop-common.c
+++ b/common/xfdesktop-common.c
@@ -53,141 +53,6 @@
 #include "xfdesktop-common.h"
 #include "xfce-backdrop.h" /* for XfceBackdropImageStyle */
 
-#ifndef O_BINARY
-#define O_BINARY  0
-#endif
-
-static GList *
-list_files_in_dir(const gchar *path)
-{
-    GDir *dir;
-    gboolean needs_slash = TRUE;
-    const gchar *file;
-    GList *files = NULL;
-
-    dir = g_dir_open(path, 0, 0);
-    if(!dir)
-        return NULL;
-
-    if(path[strlen(path)-1] == '/')
-        needs_slash = FALSE;
-
-    while((file = g_dir_read_name(dir))) {
-        gchar *current_file = g_strdup_printf(needs_slash ? "%s/%s" : "%s%s",
-                                              path, file);
-
-        files = g_list_insert_sorted(files, current_file, (GCompareFunc)g_strcmp0);
-    }
-
-    g_dir_close(dir);
-
-    return files;
-}
-
-
-gchar *
-xfdesktop_backdrop_choose_next(const gchar *filename)
-{
-    GList *files, *current_file, *start_file;
-    gchar *file = NULL;
-
-    g_return_val_if_fail(filename, NULL);
-
-    files = list_files_in_dir(g_path_get_dirname(filename));
-    if(!files)
-        return NULL;
-
-    /* Get the our current background in the list */
-    current_file = g_list_find_custom(files, filename, (GCompareFunc)g_strcmp0);
-
-    /* if somehow we don't have a valid file, grab the first one available */
-    if(current_file == NULL)
-        current_file = g_list_first(files);
-
-    start_file = current_file;
-
-    /* We want the next valid image file in the dir while making sure
-     * we don't loop on ourselves */
-    do {
-        current_file = g_list_next(current_file);
-
-        /* we hit the end of the list */
-        if(current_file == NULL)
-            current_file = g_list_first(files);
-
-        /* We went through every item in the list */
-        if(g_strcmp0(start_file->data, current_file->data) == 0)
-            break;
-
-    } while(!xfdesktop_image_file_is_valid(current_file->data));
-
-    file = g_strdup(current_file->data);
-    g_list_free_full(files, g_free);
-
-    return file;
-}
-
-gchar *
-xfdesktop_backdrop_choose_random(const gchar *filename)
-{
-    static gboolean __initialized = FALSE;
-    static gint previndex = -1;
-    GList *files;
-    gchar *file = NULL;
-    gint n_items = 0, cur_file, tries = 0;
-
-    g_return_val_if_fail(filename, NULL);
-
-    files = list_files_in_dir(g_path_get_dirname(filename));
-    if(!files)
-        return NULL;
-
-    n_items = g_list_length(files);
-
-    if(1 == n_items) {
-        file = g_strdup(g_list_first(files)->data);
-        g_list_free_full(files, g_free);
-        return file;
-    }
-
-    /* NOTE: 4.3BSD random()/srandom() are a) stronger and b) faster than
-    * ANSI-C rand()/srand(). So we use random() if available */
-    if(G_UNLIKELY(!__initialized))    {
-        guint seed = time(NULL) ^ (getpid() + (getpid() << 15));
-#ifdef HAVE_SRANDOM
-        srandom(seed);
-#else
-        srand(seed);
-#endif
-        __initialized = TRUE;
-    }
-
-    do {
-        if(tries++ == n_items) {
-            /* this isn't precise, but if we've failed to get a good
-             * image after all this time, let's just give up */
-            g_warning("Unable to find good image from list; giving up");
-            g_list_free_full(files, g_free);
-            return NULL;
-        }
-
-        do {
-#ifdef HAVE_SRANDOM
-            cur_file = random() % n_items;
-#else
-            cur_file = rand() % n_items;
-#endif
-        } while(cur_file == previndex && G_LIKELY(previndex != -1));
-
-    } while(!xfdesktop_image_file_is_valid(g_list_nth(files, cur_file)->data));
-
-    previndex = cur_file;
-
-    file = g_strdup(g_list_nth(files, cur_file)->data);
-    g_list_free_full(files, g_free);
-
-    return file;
-}
 
 gchar *
 xfdesktop_get_file_mimetype(const gchar *file)
diff --git a/common/xfdesktop-common.h b/common/xfdesktop-common.h
index 4dcec73..dde3fa40 100644
--- a/common/xfdesktop-common.h
+++ b/common/xfdesktop-common.h
@@ -53,6 +53,15 @@
 #define SINGLE_WORKSPACE_MODE     "/backdrop/single-workspace-mode"
 #define SINGLE_WORKSPACE_NUMBER   "/backdrop/single-workspace-number"
 
+#define DESKTOP_ICONS_SHOW_THUMBNAILS        "/desktop-icons/show-thumbnails"
+#define DESKTOP_ICONS_SHOW_NETWORK_REMOVABLE "/desktop-icons/file-icons/show-network-removable"
+#define DESKTOP_ICONS_SHOW_DEVICE_REMOVABLE  "/desktop-icons/file-icons/show-device-removable"
+#define DESKTOP_ICONS_SHOW_UNKNWON_REMOVABLE "/desktop-icons/file-icons/show-unknown-removable"
+#define DESKTOP_ICONS_SHOW_HOME              "/desktop-icons/file-icons/show-home"
+#define DESKTOP_ICONS_SHOW_TRASH             "/desktop-icons/file-icons/show-trash"
+#define DESKTOP_ICONS_SHOW_FILESYSTEM        "/desktop-icons/file-icons/show-filesystem"
+#define DESKTOP_ICONS_SHOW_REMOVABLE         "/desktop-icons/file-icons/show-removable"
+
 /**
  * File information namespaces queried for #GFileInfo objects.
  */
@@ -76,9 +85,6 @@
 
 G_BEGIN_DECLS
 
-gchar *xfdesktop_backdrop_choose_next(const gchar *filename);
-gchar *xfdesktop_backdrop_choose_random(const gchar *filename);
-
 gboolean xfdesktop_image_file_is_valid(const gchar *filename);
 
 gchar *xfdesktop_get_file_mimetype(const gchar *file);
diff --git a/common/xfdesktop-thumbnailer.c b/common/xfdesktop-thumbnailer.c
index 2416d8b..248a3c5 100644
--- a/common/xfdesktop-thumbnailer.c
+++ b/common/xfdesktop-thumbnailer.c
@@ -340,7 +340,7 @@ xfdesktop_thumbnailer_queue_thumbnail(XfdesktopThumbnailer *thumbnailer,
 
     if(g_slist_find(thumbnailer->priv->queue, file) == NULL) {
         thumbnailer->priv->queue = g_slist_prepend(thumbnailer->priv->queue,
-                                                   file);
+                                                   g_strdup(file));
     }
 
     thumbnailer->priv->request_timer_id = g_timeout_add_full(
@@ -370,6 +370,8 @@ void
 xfdesktop_thumbnailer_dequeue_thumbnail(XfdesktopThumbnailer *thumbnailer,
                                         gchar *file)
 {
+    GSList *item;
+
     g_return_if_fail(XFDESKTOP_IS_THUMBNAILER(thumbnailer));
     g_return_if_fail(file != NULL);
 
@@ -392,9 +394,11 @@ xfdesktop_thumbnailer_dequeue_thumbnail(XfdesktopThumbnailer *thumbnailer,
         thumbnailer->priv->handle = 0;
     }
 
-    if(g_slist_find(thumbnailer->priv->queue, file) != NULL) {
-        thumbnailer->priv->queue = g_slist_remove_all(thumbnailer->priv->queue,
-                                                      file);
+    item = g_slist_find(thumbnailer->priv->queue, file);
+    if(item != NULL) {
+        g_free(item->data);
+        thumbnailer->priv->queue = g_slist_remove(thumbnailer->priv->queue,
+                                                  file);
     }
 
     thumbnailer->priv->request_timer_id = g_timeout_add_full(
@@ -436,6 +440,7 @@ xfdesktop_thumbnailer_queue_request_timer(XfdesktopThumbnailer *thumbnailer)
             file = g_file_new_for_path(iter->data);
             uris[i] = g_file_get_uri(file);
             mimetypes[i] = xfdesktop_get_file_mimetype(iter->data);
+
             g_object_unref(file);
         }
         iter = g_slist_next(iter);
@@ -465,6 +470,18 @@ xfdesktop_thumbnailer_queue_request_timer(XfdesktopThumbnailer *thumbnailer)
         }
     }
 
+    /* Free the memory */
+    i = 0;
+    iter = thumbnailer->priv->queue;
+    while(iter) {
+        if(iter->data) {
+            g_free(uris[i]);
+            g_free(mimetypes[i]);
+        }
+        iter = g_slist_next(iter);
+        i++;
+    }
+
     g_free(uris);
     g_free(mimetypes);
 
@@ -498,7 +515,7 @@ xfdesktop_thumbnailer_thumbnail_ready_dbus(DBusGProxy *proxy,
     gchar *thumbnail_location;
     GFile *file;
     GSList *iter = thumbnailer->priv->queue;
-    gchar *f_uri, *f_uri_checksum, *filename;
+    gchar *f_uri, *f_uri_checksum, *filename, *temp;
     gchar *thumbnail_flavor;
     gint x = 0;
 
@@ -531,8 +548,8 @@ xfdesktop_thumbnailer_thumbnail_ready_dbus(DBusGProxy *proxy,
                                               filename, NULL);
 
             DBG("thumbnail-ready src: %s thumbnail: %s",
-                    (char*)iter->data,
-                    thumbnail_location);
+                (char*)iter->data,
+                thumbnail_location);
 
             g_signal_emit(G_OBJECT(thumbnailer),
                           thumbnailer_signals[THUMBNAIL_READY],
@@ -540,14 +557,17 @@ xfdesktop_thumbnailer_thumbnail_ready_dbus(DBusGProxy *proxy,
                           iter->data,
                           thumbnail_location);
 
+            temp = iter->data;
             thumbnailer->priv->queue = g_slist_remove(thumbnailer->priv->queue,
-                                                      iter->data);
+                                                      temp);
 
             iter = thumbnailer->priv->queue;
             x++;
-            
+
             g_free(filename);
             g_free(f_uri_checksum);
+            g_free(thumbnail_location);
+            g_free(temp);
         } else {
             iter = g_slist_next(iter);
         }
diff --git a/settings/main.c b/settings/main.c
index 74da46e..f5d59dd 100644
--- a/settings/main.c
+++ b/settings/main.c
@@ -75,13 +75,9 @@
 #define DESKTOP_ICONS_ICON_SIZE_PROP         "/desktop-icons/icon-size"
 #define DESKTOP_ICONS_FONT_SIZE_PROP         "/desktop-icons/font-size"
 #define DESKTOP_ICONS_CUSTOM_FONT_SIZE_PROP  "/desktop-icons/use-custom-font-size"
+#define DESKTOP_ICONS_SHOW_TOOLTIP_PROP      "/desktop-icons/show-tooltips"
+#define DESKTOP_ICONS_TOOLTIP_SIZE_PROP      "/desktop-icons/tooltip-size"
 #define DESKTOP_ICONS_SINGLE_CLICK_PROP      "/desktop-icons/single-click"
-#define DESKTOP_ICONS_SHOW_THUMBNAILS_PROP   "/desktop-icons/show-thumbnails"
-#define DESKTOP_ICONS_SHOW_HOME              "/desktop-icons/file-icons/show-home"
-#define DESKTOP_ICONS_SHOW_TRASH             "/desktop-icons/file-icons/show-trash"
-#define DESKTOP_ICONS_SHOW_FILESYSTEM        "/desktop-icons/file-icons/show-filesystem"
-#define DESKTOP_ICONS_SHOW_REMOVABLE         "/desktop-icons/file-icons/show-removable"
-
 
 typedef struct
 {
@@ -115,8 +111,10 @@ typedef struct
     gulong color1_btn_id;
     gulong color2_btn_id;
 
-    GtkWidget *backdrop_cycle_spinbox;
+    /* backdrop cycling options */
     GtkWidget *backdrop_cycle_chkbox;
+    GtkWidget *combo_backdrop_cycle_period;
+    GtkWidget *backdrop_cycle_spinbox;
     GtkWidget *random_backdrop_order_chkbox;
 
     GThread *preview_thread;
@@ -307,7 +305,7 @@ xfdesktop_settings_queue_preview(GtkTreeModel *model,
                                  GtkTreeIter *iter,
                                  AppearancePanel *panel)
 {
-    gchar *filename;
+    gchar *filename = NULL;
 
     gtk_tree_model_get(model, iter, COL_FILENAME, &filename, -1);
 
@@ -321,6 +319,9 @@ xfdesktop_settings_queue_preview(GtkTreeModel *model,
 
         xfdesktop_settings_add_file_to_queue(panel, pdata);
     }
+
+    if(filename)
+        g_free(filename);
 }
 
 static void
@@ -342,7 +343,7 @@ cb_special_icon_toggled(GtkCellRendererToggle *render, gchar *path, gpointer use
 
     xfconf_channel_set_bool(channel, icon_property, show_icon);
 
-    gtk_list_store_set(GTK_LIST_STORE(model), &iter,
+    gtk_tree_store_set(GTK_TREE_STORE(model), &iter,
                        COL_ICON_ENABLED, show_icon, -1);
 
     gtk_tree_path_free(tree_path);
@@ -354,10 +355,10 @@ setup_special_icon_list(GtkBuilder *gxml,
                         XfconfChannel *channel)
 {
     GtkWidget *treeview;
-    GtkListStore *ls;
+    GtkTreeStore *ts;
     GtkTreeViewColumn *col;
     GtkCellRenderer *render;
-    GtkTreeIter iter;
+    GtkTreeIter iter, parent_iter, child_iter;
     const struct {
         const gchar *name;
         const gchar *icon;
@@ -373,14 +374,21 @@ setup_special_icon_list(GtkBuilder *gxml,
           DESKTOP_ICONS_SHOW_TRASH, TRUE },
         { N_("Removable Devices"), "drive-removable-media", "gnome-dev-removable",
           DESKTOP_ICONS_SHOW_REMOVABLE, TRUE },
+        { N_("Network Shares"), "network_fs", "gnome-dev-network",
+          DESKTOP_ICONS_SHOW_NETWORK_REMOVABLE, TRUE },
+        { N_("Disks and Drives"), "drive-harddisk-usb", "gnome-dev-removable-usb",
+          DESKTOP_ICONS_SHOW_DEVICE_REMOVABLE, TRUE },
+        { N_("Other Items"), "phone-symbolic", "phone",
+          DESKTOP_ICONS_SHOW_UNKNWON_REMOVABLE, TRUE },
         { NULL, NULL, NULL, NULL, FALSE },
     };
+    const int REMOVABLE_DEVICES = 4;
     int i, w;
     GtkIconTheme *itheme = gtk_icon_theme_get_default();
 
     gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &w, NULL);
 
-    ls = gtk_list_store_new(N_ICON_COLS, GDK_TYPE_PIXBUF, G_TYPE_STRING,
+    ts = gtk_tree_store_new(N_ICON_COLS, GDK_TYPE_PIXBUF, G_TYPE_STRING,
                             G_TYPE_BOOLEAN, G_TYPE_STRING);
     for(i = 0; icons[i].name; ++i) {
         GdkPixbuf *pix = NULL;
@@ -390,8 +398,15 @@ setup_special_icon_list(GtkBuilder *gxml,
         else
             pix = gtk_icon_theme_load_icon(itheme, icons[i].icon_fallback, w, 0, NULL);
 
-        gtk_list_store_append(ls, &iter);
-        gtk_list_store_set(ls, &iter,
+        if(i < REMOVABLE_DEVICES) {
+            gtk_tree_store_append(ts, &parent_iter, NULL);
+            iter = parent_iter;
+        } else {
+            gtk_tree_store_append(ts, &child_iter, &parent_iter);
+            iter = child_iter;
+        }
+
+        gtk_tree_store_set(ts, &iter,
                            COL_ICON_NAME, _(icons[i].name),
                            COL_ICON_PIX, pix,
                            COL_ICON_PROPERTY, icons[i].xfconf_property,
@@ -424,8 +439,8 @@ setup_special_icon_list(GtkBuilder *gxml,
     gtk_tree_view_column_pack_start(col, render, TRUE);
     gtk_tree_view_column_add_attribute(col, render, "text", COL_ICON_NAME);
 
-    gtk_tree_view_set_model(GTK_TREE_VIEW(treeview), GTK_TREE_MODEL(ls));
-    g_object_unref(G_OBJECT(ls));
+    gtk_tree_view_set_model(GTK_TREE_VIEW(treeview), GTK_TREE_MODEL(ts));
+    g_object_unref(G_OBJECT(ts));
 }
 
 
@@ -856,9 +871,11 @@ xfdesktop_settings_get_active_workspace(AppearancePanel *panel,
     return workspace_num;
 }
 
+/* This works for both the custom font size and show tooltips check buttons,
+ * it just enables the associated spin button */
 static void
-cb_xfdesktop_chk_custom_font_size_toggled(GtkCheckButton *button,
-                                          gpointer user_data)
+cb_xfdesktop_chk_button_toggled(GtkCheckButton *button,
+                                gpointer user_data)
 {
     GtkWidget *spin_button = GTK_WIDGET(user_data);
 
@@ -869,11 +886,61 @@ cb_xfdesktop_chk_custom_font_size_toggled(GtkCheckButton *button,
 }
 
 static void
+update_backdrop_random_order_chkbox(AppearancePanel *panel)
+{
+    gboolean sensitive = FALSE;
+    gint period;
+
+    /* For the random check box to be active the combo_backdrop_cycle_period
+     * needs to be active and needs to not be set to chronological */
+    if(gtk_widget_get_sensitive(panel->combo_backdrop_cycle_period)) {
+        period = gtk_combo_box_get_active(GTK_COMBO_BOX(panel->combo_backdrop_cycle_period));
+        if(period != XFCE_BACKDROP_PERIOD_CHRONOLOGICAL)
+            sensitive = TRUE;
+    }
+
+    gtk_widget_set_sensitive(panel->random_backdrop_order_chkbox, sensitive);
+}
+
+static void
+update_backdrop_cycle_spinbox(AppearancePanel *panel)
+{
+    gboolean sensitive = FALSE;
+    gint period;
+
+    /* For the spinbox to be active the combo_backdrop_cycle_period needs to be
+     * active and needs to be set to something where the spinbox would apply */
+    if(gtk_widget_get_sensitive(panel->combo_backdrop_cycle_period)) {
+        period = gtk_combo_box_get_active(GTK_COMBO_BOX(panel->combo_backdrop_cycle_period));
+        if(period == XFCE_BACKDROP_PERIOD_SECONDS ||
+           period == XFCE_BACKDROP_PERIOD_MINUES  ||
+           period == XFCE_BACKDROP_PERIOD_HOURS)
+        {
+            sensitive = TRUE;
+        }
+    }
+
+    gtk_widget_set_sensitive(panel->backdrop_cycle_spinbox, sensitive);
+}
+
+static void
+cb_combo_backdrop_cycle_period_change(GtkComboBox *combo,
+                                      gpointer user_data)
+{
+    AppearancePanel *panel = user_data;
+
+    /* determine if the spin box should be sensitive */
+    update_backdrop_cycle_spinbox(panel);
+    /* determine if the random check box should be sensitive */
+    update_backdrop_random_order_chkbox(panel);
+}
+
+static void
 cb_xfdesktop_chk_cycle_backdrop_toggled(GtkCheckButton *button,
                                         gpointer user_data)
 {
-    gboolean sensitive = FALSE;
     AppearancePanel *panel = user_data;
+    gboolean sensitive = FALSE;
 
     TRACE("entering");
 
@@ -881,8 +948,12 @@ cb_xfdesktop_chk_cycle_backdrop_toggled(GtkCheckButton *button,
            sensitive = TRUE;
     }
 
-    gtk_widget_set_sensitive(panel->backdrop_cycle_spinbox, sensitive);
-    gtk_widget_set_sensitive(panel->random_backdrop_order_chkbox, sensitive);
+    /* The cycle backdrop toggles the period and random widgets */
+    gtk_widget_set_sensitive(panel->combo_backdrop_cycle_period, sensitive);
+    /* determine if the spin box should be sensitive */
+    update_backdrop_cycle_spinbox(panel);
+    /* determine if the random check box should be sensitive */
+    update_backdrop_random_order_chkbox(panel);
 }
 
 static gboolean
@@ -979,6 +1050,7 @@ cb_folder_selection_changed(GtkWidget *button,
         DBG("filename %s, previous_filename %s. Nothing changed",
             filename == NULL ? "NULL" : filename,
             previous_filename == NULL ? "NULL" : previous_filename);
+
         g_free(filename);
         g_free(previous_filename);
         return;
@@ -1096,7 +1168,9 @@ xfdesktop_settings_update_iconview_folder(AppearancePanel *panel)
 }
 
 /* This function is to add or remove all the bindings for the background
- * tab. It's intended to be used when the app changes monitors or workspaces */
+ * tab. It's intended to be used when the app changes monitors or workspaces.
+ * It reverts the items back to their defaults before binding any new settings
+ * that way if the setting isn't present, the default correctly displays. */
 static void
 xfdesktop_settings_background_tab_change_bindings(AppearancePanel *panel,
                                                   gboolean remove_binding)
@@ -1180,6 +1254,13 @@ xfdesktop_settings_background_tab_change_bindings(AppearancePanel *panel,
                 gtk_color_button_set_color(GTK_COLOR_BUTTON(panel->color1_btn),
                                            g_value_get_boxed(&value));
                 g_value_unset(&value);
+            } else {
+                /* revert to showing our default color */
+                GdkColor color1;
+                color1.red = 0x1515;
+                color1.green = 0x2222;
+                color1.blue = 0x3333;
+                gtk_color_button_set_color(GTK_COLOR_BUTTON(panel->color1_btn), &color1);
             }
 
             g_free(old_property);
@@ -1208,6 +1289,13 @@ xfdesktop_settings_background_tab_change_bindings(AppearancePanel *panel,
                 gtk_color_button_set_color(GTK_COLOR_BUTTON(panel->color1_btn),
                                            g_value_get_boxed(&value));
                 g_value_unset(&value);
+            } else {
+                /* revert to showing our default color */
+                GdkColor color2;
+                color2.red = 0x1515;
+                color2.green = 0x2222;
+                color2.blue = 0x3333;
+                gtk_color_button_set_color(GTK_COLOR_BUTTON(panel->color2_btn), &color2);
             }
 
             g_free(old_property);
@@ -1226,11 +1314,30 @@ xfdesktop_settings_background_tab_change_bindings(AppearancePanel *panel,
         xfconf_g_property_unbind_by_property(channel, buf,
                            G_OBJECT(panel->backdrop_cycle_chkbox), "active");
     } else {
+        /* The default is disable cycling, set that before we bind to anything */
+        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(panel->backdrop_cycle_chkbox), FALSE);
+
         xfconf_g_property_bind(channel, buf, G_TYPE_BOOLEAN,
                                G_OBJECT(panel->backdrop_cycle_chkbox), "active");
     }
     g_free(buf);
 
+    /* backdrop cycle period combo box */
+    buf = xfdesktop_settings_generate_per_workspace_binding_string(panel, "backdrop-cycle-period");
+    if(remove_binding) {
+        xfconf_g_property_unbind_by_property(channel, buf,
+                               G_OBJECT(panel->combo_backdrop_cycle_period), "active");
+    } else {
+        /* default is minutes, set that before we bind to it */
+        gtk_combo_box_set_active(GTK_COMBO_BOX(panel->combo_backdrop_cycle_period), XFCE_BACKDROP_PERIOD_MINUES);
+
+        xfconf_g_property_bind(channel, buf, G_TYPE_INT,
+                               G_OBJECT(panel->combo_backdrop_cycle_period), "active");
+        /* determine if the cycle timer spin box is sensitive */
+        cb_combo_backdrop_cycle_period_change(GTK_COMBO_BOX(panel->combo_backdrop_cycle_period), panel);
+    }
+    g_free(buf);
+
     /* cycle timer spin box */
     buf = xfdesktop_settings_generate_per_workspace_binding_string(panel, "backdrop-cycle-timer");
     if(remove_binding) {
@@ -1238,6 +1345,10 @@ xfdesktop_settings_background_tab_change_bindings(AppearancePanel *panel,
                    G_OBJECT(gtk_spin_button_get_adjustment(GTK_SPIN_BUTTON(panel->backdrop_cycle_spinbox))),
                    "value");
     } else {
+        guint current_timer = xfconf_channel_get_uint(channel, buf, 10);
+        /* Update the spin box before we bind to it */
+        gtk_spin_button_set_value(GTK_SPIN_BUTTON(panel->backdrop_cycle_spinbox), current_timer);
+
         xfconf_g_property_bind(channel, buf, G_TYPE_UINT,
                        G_OBJECT(gtk_spin_button_get_adjustment(GTK_SPIN_BUTTON(panel->backdrop_cycle_spinbox))),
                        "value");
@@ -1250,11 +1361,13 @@ xfdesktop_settings_background_tab_change_bindings(AppearancePanel *panel,
         xfconf_g_property_unbind_by_property(channel, buf,
                            G_OBJECT(panel->random_backdrop_order_chkbox), "active");
     } else {
+        /* The default is sequential, set that before we bind to anything */
+        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(panel->random_backdrop_order_chkbox), FALSE);
+
         xfconf_g_property_bind(channel, buf, G_TYPE_BOOLEAN,
                                G_OBJECT(panel->random_backdrop_order_chkbox), "active");
     }
     g_free(buf);
-
 }
 
 static void
@@ -1320,6 +1433,8 @@ cb_update_background_tab(WnckWindow *wnck_window,
 
     if(panel->monitor_name != NULL)
         g_free(panel->monitor_name);
+    if(monitor_name != NULL)
+        g_free(monitor_name);
 
     panel->workspace = workspace_num;
     panel->screen = screen_num;
@@ -1504,7 +1619,7 @@ xfdesktop_settings_dialog_setup_tabs(GtkBuilder *main_gxml,
     GtkWidget *appearance_container, *chk_custom_font_size,
               *spin_font_size, *w, *box, *spin_icon_size,
               *chk_show_thumbnails, *chk_single_click, *appearance_settings,
-              *bnt_exit;
+              *chk_show_tooltips, *spin_tooltip_size, *bnt_exit;
     GtkBuilder *appearance_gxml;
     AppearancePanel *panel = g_new0(AppearancePanel, 1);
     GError *error = NULL;
@@ -1544,10 +1659,20 @@ xfdesktop_settings_dialog_setup_tabs(GtkBuilder *main_gxml,
     chk_single_click = GTK_WIDGET(gtk_builder_get_object(main_gxml,
                                                          "chk_single_click"));
 
+    /* tooltip options */
+    chk_show_tooltips = GTK_WIDGET(gtk_builder_get_object(main_gxml, "chk_show_tooltips"));
+    spin_tooltip_size = GTK_WIDGET(gtk_builder_get_object(main_gxml, "spin_tooltip_size"));
+    gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin_tooltip_size), 128);
+
+    /* connect up the signals */
     g_signal_connect(G_OBJECT(chk_custom_font_size), "toggled",
-                     G_CALLBACK(cb_xfdesktop_chk_custom_font_size_toggled),
+                     G_CALLBACK(cb_xfdesktop_chk_button_toggled),
                      spin_font_size);
 
+    g_signal_connect(G_OBJECT(chk_show_tooltips), "toggled",
+                     G_CALLBACK(cb_xfdesktop_chk_button_toggled),
+                     spin_tooltip_size);
+
     /* thumbnails */
     chk_show_thumbnails = GTK_WIDGET(gtk_builder_get_object(main_gxml,
                                                             "chk_show_thumbnails"));
@@ -1659,15 +1784,24 @@ xfdesktop_settings_dialog_setup_tabs(GtkBuilder *main_gxml,
     /* background cycle timer */
     panel->backdrop_cycle_chkbox = GTK_WIDGET(gtk_builder_get_object(appearance_gxml,
                                                                      "chk_cycle_backdrop"));
+    panel->combo_backdrop_cycle_period = GTK_WIDGET(gtk_builder_get_object(appearance_gxml,
+                                                                           "combo_cycle_backdrop_period"));
     panel->backdrop_cycle_spinbox = GTK_WIDGET(gtk_builder_get_object(appearance_gxml,
-                                                                     "spin_backdrop_time_minutes"));
+                                                                     "spin_backdrop_time"));
     panel->random_backdrop_order_chkbox = GTK_WIDGET(gtk_builder_get_object(appearance_gxml,
                                                                      "chk_random_backdrop_order"));
 
+    /* Pick the first entry so something shows up */
+    gtk_combo_box_set_active(GTK_COMBO_BOX(panel->combo_backdrop_cycle_period), XFCE_BACKDROP_PERIOD_MINUES);
+
     g_signal_connect(G_OBJECT(panel->backdrop_cycle_chkbox), "toggled",
                     G_CALLBACK(cb_xfdesktop_chk_cycle_backdrop_toggled),
                     panel);
 
+    g_signal_connect(G_OBJECT(panel->combo_backdrop_cycle_period), "changed",
+                     G_CALLBACK(cb_combo_backdrop_cycle_period_change),
+                     panel);
+
     g_object_unref(G_OBJECT(appearance_gxml));
 
 
@@ -1730,7 +1864,13 @@ xfdesktop_settings_dialog_setup_tabs(GtkBuilder *main_gxml,
     xfconf_g_property_bind(channel, DESKTOP_ICONS_CUSTOM_FONT_SIZE_PROP,
                            G_TYPE_BOOLEAN, G_OBJECT(chk_custom_font_size),
                            "active");
-    xfconf_g_property_bind(channel, DESKTOP_ICONS_SHOW_THUMBNAILS_PROP,
+    xfconf_g_property_bind(channel, DESKTOP_ICONS_SHOW_TOOLTIP_PROP,
+                           G_TYPE_BOOLEAN, G_OBJECT(chk_show_tooltips),
+                           "active");
+    xfconf_g_property_bind(channel, DESKTOP_ICONS_TOOLTIP_SIZE_PROP, G_TYPE_DOUBLE,
+                           G_OBJECT(gtk_spin_button_get_adjustment(GTK_SPIN_BUTTON(spin_tooltip_size))),
+                           "value");
+    xfconf_g_property_bind(channel, DESKTOP_ICONS_SHOW_THUMBNAILS,
                            G_TYPE_BOOLEAN, G_OBJECT(chk_show_thumbnails),
                            "active");
     xfconf_g_property_bind(channel, DESKTOP_ICONS_SINGLE_CLICK_PROP,
diff --git a/settings/xfdesktop-settings-appearance-frame-ui.glade b/settings/xfdesktop-settings-appearance-frame-ui.glade
index 32e10c0..f992dae 100644
--- a/settings/xfdesktop-settings-appearance-frame-ui.glade
+++ b/settings/xfdesktop-settings-appearance-frame-ui.glade
@@ -96,7 +96,7 @@
                         <property name="can_focus">True</property>
                         <property name="receives_default">True</property>
                         <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="tooltip-text" translatable="yes">Add an image to the list</property>
+                        <property name="tooltip-text" translatable="yes">Choose the folder to select wallpapers from</property>
                         <property name="action">GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER</property>
                       </object>
                       <packing>
@@ -143,7 +143,6 @@
                         <property name="visible">True</property>
                         <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
                         <property name="tooltip-text" translatable="yes">Specify how the image will be resized to fit the screen</property>
-                        <signal handler="image_style_changed" name="changed"/>
                         <items>
                           <item translatable="yes">None</item>
                           <item translatable="yes">Centered</item>
@@ -184,7 +183,6 @@
                         <property name="visible">True</property>
                         <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
                         <property name="tooltip-text" translatable="yes">Specify the style of the color drawn behind the backdrop image</property>
-                        <signal handler="color_style_changed" name="changed"/>
                         <property name="model">model2</property>
                         <child>
                           <object class="GtkCellRendererText" id="renderer2"/>
@@ -211,7 +209,6 @@
                         <property name="tooltip-text" translatable="yes">Specifies the solid color, or the "left" or "top" color of the gradient</property>
                         <property name="title" translatable="yes">Select First Color</property>
                         <property name="color">#151522223333</property>
-                        <signal handler="color1_changed" name="color_set"/>
                       </object>
                       <packing>
                         <property name="left-attach">2</property>
@@ -231,7 +228,6 @@
                         <property name="tooltip-text" translatable="yes">Specifies the "right" or "bottom" color of the gradient</property>
                         <property name="title" translatable="yes">Select Second Color</property>
                         <property name="color">#151522223333</property>
-                        <signal handler="color2_changed" name="color_set"/>
                       </object>
                       <packing>
                         <property name="left-attach">3</property>
@@ -278,8 +274,8 @@
                         <property name="sensitive">True</property>
                         <property name="can_focus">True</property>
                         <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="label" translatable="yes">_Change the background (in minutes):</property>
-                        <property name="tooltip-text" translatable="yes">Automatically select a different background from the current directory after a set number of minutes.</property>
+                        <property name="label" translatable="yes">_Change the background </property>
+                        <property name="tooltip-text" translatable="yes">Automatically select a different background from the current directory.</property>
                         <property name="use_underline">True</property>
                         <property name="draw_indicator">True</property>
                       </object>
@@ -288,13 +284,33 @@
                       </packing>
                     </child>
                     <child>
-                      <object class="GtkSpinButton" id="spin_backdrop_time_minutes">
+                      <object class="GtkComboBoxText" id="combo_cycle_backdrop_period">
+                        <property name="visible">True</property>
+                        <property name="sensitive">False</property>
+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                        <property name="tooltip-text" translatable="yes">Specify how often the background will change</property>
+                        <items>
+                          <item translatable="yes">in seconds:</item>
+                          <item translatable="yes">in minutes:</item>
+                          <item translatable="yes">in hours:</item>
+                          <item translatable="yes">at start up</item>
+                          <item translatable="yes">every hour</item>
+                          <item translatable="yes">every day</item>
+                          <item translatable="yes">chronologically</item>
+                        </items>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkSpinButton" id="spin_backdrop_time">
                         <property name="visible">True</property>
                         <property name="sensitive">False</property>
                         <property name="can_focus">True</property>
                         <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
                         <property name="adjustment">adjustment3</property>
-                        <property name="tooltip-text" translatable="yes">Number of minutes before a different background is selected.</property>
+                        <property name="tooltip-text" translatable="yes">Amount of time before a different background is selected.</property>
                       </object>
                       <packing>
                         <property name="expand">False</property>
@@ -310,6 +326,7 @@
                         <property name="label" translatable="yes">_Random Order</property>
                         <property name="use_underline">True</property>
                         <property name="draw_indicator">True</property>
+                        <property name="tooltip-text" translatable="yes">Randomly selects another image from the same directory when the wallpaper is to cycle. Overrides the Chronological option.</property>
                       </object>
                       <packing>
                         <property name="expand">False</property>
diff --git a/settings/xfdesktop-settings-ui.glade b/settings/xfdesktop-settings-ui.glade
index b69fe4b..ff04b37 100644
--- a/settings/xfdesktop-settings-ui.glade
+++ b/settings/xfdesktop-settings-ui.glade
@@ -11,12 +11,20 @@
   </object>
   <object class="GtkAdjustment" id="adjustment4">
     <property name="upper">144</property>
-    <property name="lower">4</property>
+    <property name="lower">0</property>
     <property name="page_increment">10</property>
     <property name="step_increment">1</property>
     <property name="page_size">0</property>
     <property name="value">12</property>
   </object>
+  <object class="GtkAdjustment" id="adjustment_tooltip">
+    <property name="upper">256</property>
+    <property name="lower">0</property>
+    <property name="page_increment">10</property>
+    <property name="step_increment">1</property>
+    <property name="page_size">0</property>
+    <property name="value">128</property>
+  </object>
   <object class="GtkListStore" id="model3">
     <columns>
       <column type="gchararray"/>
@@ -635,6 +643,45 @@
                                   </object>
                                 </child>
                                 <child>
+                                  <object class="GtkHBox" id="hboxtooltip">
+                                    <property name="visible">True</property>
+                                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                                    <property name="spacing">4</property>
+                                    <child>
+                                      <object class="GtkCheckButton" id="chk_show_tooltips">
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">True</property>
+                                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                                        <property name="label" translatable="yes">Show icon tooltips. Size:</property>
+                                        <property name="use_underline">True</property>
+                                        <property name="draw_indicator">True</property>
+                                        <property name="active">True</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkSpinButton" id="spin_tooltip_size">
+                                        <property name="visible">True</property>
+                                        <property name="sensitive">True</property>
+                                        <property name="can_focus">True</property>
+                                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                                        <property name="adjustment">adjustment_tooltip</property>
+                                        <property name="tooltip-text" translatable="yes">Size of the tooltip preview image.</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="position">1</property>
+                                      </packing>
+                                    </child>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="position">2</property>
+                                  </packing>
+                                </child>
+                                <child>
                                   <object class="GtkHBox" id="hbox9">
                                     <property name="visible">True</property>
                                     <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
diff --git a/src/xfce-backdrop.c b/src/xfce-backdrop.c
index 6344288..929c6ee 100644
--- a/src/xfce-backdrop.c
+++ b/src/xfce-backdrop.c
@@ -45,7 +45,11 @@
 #define abs(x)  ( (x) < 0 ? -(x) : (x) )
 #endif
 
-#define XFCE_BACKDROP_BUFFER_SIZE 4096
+#define XFCE_BACKDROP_BUFFER_SIZE 32768
+
+#ifndef O_BINARY
+#define O_BINARY  0
+#endif
 
 typedef struct _XfceBackdropImageData XfceBackdropImageData;
 
@@ -80,6 +84,10 @@ static void xfce_backdrop_file_input_stream_ready_cb(GObject *source_object,
 
 static void xfce_backdrop_image_data_release(XfceBackdropImageData *image_data);
 
+gchar *xfce_backdrop_choose_next         (const gchar *filename);
+gchar *xfce_backdrop_choose_random       (const gchar *filename);
+gchar *xfce_backdrop_choose_chronological(const gchar *filename);
+
 struct _XfceBackdropPriv
 {
     gint width, height;
@@ -98,6 +106,7 @@ struct _XfceBackdropPriv
     gboolean cycle_backdrop;
     guint cycle_timer;
     guint cycle_timer_id;
+    XfceBackdropCyclePeriod cycle_period;
     gboolean random_backdrop_order;
 };
 
@@ -130,8 +139,9 @@ enum
     PROP_IMAGE_FILENAME,
     PROP_BRIGHTNESS,
     PROP_BACKDROP_CYCLE_ENABLE,
+    PROP_BACKDROP_CYCLE_PERIOD,
     PROP_BACKDROP_CYCLE_TIMER,
-    PROP_BACKDROP_RANDOM_ORDER
+    PROP_BACKDROP_RANDOM_ORDER,
 };
 
 static guint backdrop_signals[LAST_SIGNAL] = { 0, };
@@ -230,6 +240,210 @@ xfce_backdrop_clear_cached_image(XfceBackdrop *backdrop)
     backdrop->priv->pix = NULL;
 }
 
+/* Returns a GList of all the files in the parent directory of filename */
+static GList *
+list_files_in_dir(const gchar *filename)
+{
+    GDir *dir;
+    gboolean needs_slash = TRUE;
+    const gchar *file;
+    GList *files = NULL;
+    gchar *dir_name;
+
+    dir_name = g_path_get_dirname(filename);
+
+    dir = g_dir_open(dir_name, 0, 0);
+    if(!dir) {
+        g_free(dir_name);
+        return NULL;
+    }
+
+    if(dir_name[strlen(dir_name)-1] == '/')
+        needs_slash = FALSE;
+
+    while((file = g_dir_read_name(dir))) {
+        gchar *current_file = g_strdup_printf(needs_slash ? "%s/%s" : "%s%s",
+                                              dir_name, file);
+
+        files = g_list_insert_sorted(files, current_file, (GCompareFunc)g_strcmp0);
+    }
+
+    g_dir_close(dir);
+    g_free(dir_name);
+
+    return files;
+}
+
+/* Gets the next valid image file in the folder. Free when done using it
+ * returns NULL on fail. */
+gchar *
+xfce_backdrop_choose_next(const gchar *filename)
+{
+    GList *files, *current_file, *start_file;
+    gchar *file = NULL;
+
+    TRACE("entering");
+
+    g_return_val_if_fail(filename, NULL);
+
+    /* We don't cache the list at all. This way the user can add/remove items
+     * whenever they like without xfdesktop having to do anything. If we start
+     * supporting sub-directories we may want to re-think that assumption */
+    files = list_files_in_dir(filename);
+
+    if(!files)
+        return NULL;
+
+    /* Get the our current background in the list */
+    current_file = g_list_find_custom(files, filename, (GCompareFunc)g_strcmp0);
+
+    /* if somehow we don't have a valid file, grab the first one available */
+    if(current_file == NULL)
+        current_file = g_list_first(files);
+
+    start_file = current_file;
+
+    /* We want the next valid image file in the dir while making sure
+     * we don't loop on ourselves */
+    do {
+        current_file = g_list_next(current_file);
+
+        /* we hit the end of the list */
+        if(current_file == NULL)
+            current_file = g_list_first(files);
+
+        /* We went through every item in the list */
+        if(g_strcmp0(start_file->data, current_file->data) == 0)
+            break;
+
+    } while(!xfdesktop_image_file_is_valid(current_file->data));
+
+    /* Keep a copy of our new item, free everything else */
+    file = g_strdup(current_file->data);
+    g_list_free_full(files, g_free);
+
+    return file;
+}
+
+/* Gets a random valid image file in the folder. Free when done using it.
+ * returns NULL on fail. */
+gchar *
+xfce_backdrop_choose_random(const gchar *filename)
+{
+    static gint previndex = -1;
+    GList *files;
+    gchar *file = NULL;
+    gint n_items = 0, cur_file, tries = 0;
+
+    TRACE("entering");
+
+    g_return_val_if_fail(filename, NULL);
+
+    /* We don't cache the list at all. This way the user can add/remove items
+     * whenever they like without xfdesktop having to do anything. If we start
+     * supporting sub-directories we may want to re-think that assumption */
+    files = list_files_in_dir(filename);
+
+    if(!files)
+        return NULL;
+
+    n_items = g_list_length(files);
+
+    /* If there's only 1 item, just return it, easy */
+    if(1 == n_items) {
+        file = g_strdup(g_list_first(files)->data);
+        g_list_free_full(files, g_free);
+        return file;
+    }
+
+    do {
+        if(tries++ == n_items) {
+            /* this isn't precise, but if we've failed to get a good
+             * image after all this time, let's just give up */
+            g_warning("Unable to find good image from list; giving up");
+            g_list_free_full(files, g_free);
+            return NULL;
+        }
+
+        do {
+            /* g_random_int_range bounds to n_items-1 */
+            cur_file = g_random_int_range(0, n_items);
+        } while(cur_file == previndex && G_LIKELY(previndex != -1));
+
+    } while(!xfdesktop_image_file_is_valid(g_list_nth(files, cur_file)->data));
+
+    previndex = cur_file;
+
+    /* Keep a copy of our new random item, free everything else */
+    file = g_strdup(g_list_nth(files, cur_file)->data);
+    g_list_free_full(files, g_free);
+
+    return file;
+}
+
+/* Provides a mapping of image files in the parent folder of file. It selects
+ * the image based on the hour of the day scaled for how many images are in
+ * the directory, using the first 24 if there are more.
+ * Returns a new image path or NULL on failure. Free when done using it. */
+gchar *
+xfce_backdrop_choose_chronological(const gchar *filename)
+{
+    GDateTime *datetime;
+    GList *files, *current_file, *start_file;
+    gchar *file = NULL;
+    gint n_items = 0, epoch;
+
+    TRACE("entering");
+
+    g_return_val_if_fail(filename, NULL);
+
+    /* We don't cache the list at all. This way the user can add/remove items
+     * whenever they like without xfdesktop having to do anything. If we start
+     * supporting sub-directories we may want to re-think that assumption */
+    files = list_files_in_dir(filename);
+
+    if(!files)
+        return NULL;
+
+    n_items = g_list_length(files);
+
+    /* If there's only 1 item, just return it, easy */
+    if(1 == n_items) {
+        file = g_strdup(g_list_first(files)->data);
+        g_list_free_full(files, g_free);
+        return file;
+    }
+
+    datetime = g_date_time_new_now_local();
+
+    /* Figure out which image to display based on what time of day it is
+     * and how many images we have to work with */
+    epoch = (gdouble)g_date_time_get_hour(datetime) / (24.0f / MIN(n_items, 24.0f));
+    DBG("epoch %d, hour %d, items %d", epoch, g_date_time_get_minute(datetime), n_items);
+
+    start_file = current_file = g_list_nth(files, epoch);
+
+    /* We want the next valid image file in the dir while making sure
+     * we don't loop on ourselves */
+    while(!xfdesktop_image_file_is_valid(current_file->data)) {
+        current_file = g_list_next(current_file);
+
+        /* we hit the end of the list */
+        if(current_file == NULL)
+            current_file = g_list_first(files);
+
+        /* We went through every item in the list */
+        if(g_strcmp0(start_file->data, current_file->data) == 0)
+            break;
+    }
+
+    /* Keep a copy of our new item, free everything else */
+    file = g_strdup(current_file->data);
+    g_list_free_full(files, g_free);
+    g_date_time_unref(datetime);
+
+    return file;
+}
 
 /* gobject-related functions */
 
@@ -317,12 +531,20 @@ xfce_backdrop_class_init(XfceBackdropClass *klass)
                                                          FALSE,
                                                          XFDESKTOP_PARAM_FLAGS));
 
+    g_object_class_install_property(gobject_class, PROP_BACKDROP_CYCLE_PERIOD,
+                                    g_param_spec_enum("backdrop-cycle-period",
+                                                      "backdrop-cycle-period",
+                                                      "backdrop-cycle-period",
+                                                      XFCE_TYPE_BACKDROP_CYCLE_PERIOD,
+                                                      XFCE_BACKDROP_PERIOD_MINUES,
+                                                      XFDESKTOP_PARAM_FLAGS));
+
     g_object_class_install_property(gobject_class, PROP_BACKDROP_CYCLE_TIMER,
                                     g_param_spec_uint("backdrop-cycle-timer",
-                                                     "backdrop-cycle-timer",
-                                                     "backdrop-cycle-timer",
-                                                     0, G_MAXUSHORT, 10,
-                                                     XFDESKTOP_PARAM_FLAGS));
+                                                      "backdrop-cycle-timer",
+                                                      "backdrop-cycle-timer",
+                                                      0, G_MAXUSHORT, 10,
+                                                      XFDESKTOP_PARAM_FLAGS));
 
     g_object_class_install_property(gobject_class, PROP_BACKDROP_RANDOM_ORDER,
                                     g_param_spec_boolean("backdrop-cycle-random-order",
@@ -409,6 +631,10 @@ xfce_backdrop_set_property(GObject *object,
             xfce_backdrop_set_cycle_backdrop(backdrop, g_value_get_boolean(value));
             break;
 
+        case PROP_BACKDROP_CYCLE_PERIOD:
+            xfce_backdrop_set_cycle_period(backdrop, g_value_get_enum(value));
+            break;
+
         case PROP_BACKDROP_CYCLE_TIMER:
             xfce_backdrop_set_cycle_timer(backdrop, g_value_get_uint(value));
             break;
@@ -457,6 +683,10 @@ xfce_backdrop_get_property(GObject *object,
             g_value_set_boolean(value, xfce_backdrop_get_cycle_backdrop(backdrop));
             break;
 
+        case PROP_BACKDROP_CYCLE_PERIOD:
+            g_value_set_enum(value, xfce_backdrop_get_cycle_period(backdrop));
+            break;
+
         case PROP_BACKDROP_CYCLE_TIMER:
             g_value_set_uint(value, xfce_backdrop_get_cycle_timer(backdrop));
             break;
@@ -664,7 +894,7 @@ xfce_backdrop_get_second_color(XfceBackdrop *backdrop,
  **/
 void
 xfce_backdrop_set_image_style(XfceBackdrop *backdrop,
-        XfceBackdropImageStyle style)
+                              XfceBackdropImageStyle style)
 {
     g_return_if_fail(XFCE_IS_BACKDROP(backdrop));
     
@@ -690,7 +920,7 @@ xfce_backdrop_get_image_style(XfceBackdrop *backdrop)
  *
  * Sets the image that should be used with the #XfceBackdrop.  The image will
  * be composited on top of the color (or color gradient).  To clear the image,
- * use this call with a @filename argument of %NULL.
+ * use this call with a @filename argument of %NULL. Makes a copy of @filename.
  **/
 void
 xfce_backdrop_set_image_filename(XfceBackdrop *backdrop, const gchar *filename)
@@ -699,6 +929,10 @@ xfce_backdrop_set_image_filename(XfceBackdrop *backdrop, const gchar *filename)
 
     TRACE("entering, filename %s", filename);
 
+    /* Don't do anything if the filename doesn't change */
+    if(g_strcmp0(backdrop->priv->image_path, filename) == 0)
+        return;
+
     g_free(backdrop->priv->image_path);
     
     if(filename)
@@ -718,53 +952,196 @@ xfce_backdrop_get_image_filename(XfceBackdrop *backdrop)
     return backdrop->priv->image_path;
 }
 
+static void
+xfce_backdrop_cycle_backdrop(XfceBackdrop *backdrop)
+{
+    XfceBackdropCyclePeriod period;
+    gchar *current_backdrop, *new_backdrop;
+
+    TRACE("entering");
+
+    g_return_if_fail(XFCE_IS_BACKDROP(backdrop));
+
+    current_backdrop = backdrop->priv->image_path;
+    period = backdrop->priv->cycle_period;
+
+    /* sanity checks */
+    if(current_backdrop == NULL || !backdrop->priv->cycle_backdrop)
+        return;
+
+    if(period == XFCE_BACKDROP_PERIOD_CHRONOLOGICAL) {
+        /* chronological first */
+        new_backdrop = xfce_backdrop_choose_chronological(current_backdrop);
+    } else if(backdrop->priv->random_backdrop_order) {
+        /* then random */
+        new_backdrop = xfce_backdrop_choose_random(current_backdrop);
+    } else {
+        /* sequential, the default */
+        new_backdrop = xfce_backdrop_choose_next(current_backdrop);
+    }
+
+    /* Only emit the cycle signal if something changed */
+    if(g_strcmp0(backdrop->priv->image_path, new_backdrop) != 0) {
+        xfce_backdrop_set_image_filename(backdrop, new_backdrop);
+        g_signal_emit(G_OBJECT(backdrop), backdrop_signals[BACKDROP_CYCLE], 0);
+    }
+
+    g_free(new_backdrop);
+}
+
 static gboolean
 xfce_backdrop_timer(XfceBackdrop *backdrop)
 {
+    GDateTime *local_time = NULL;
+    gint hour, minute, second;
+    guint cycle_interval = 0;
+    gboolean continue_cycling = TRUE;
+
     TRACE("entering");
 
     g_return_val_if_fail(XFCE_IS_BACKDROP(backdrop), FALSE);
 
     /* Don't bother with trying to cycle a backdrop if we're not using images */
     if(backdrop->priv->image_style != XFCE_BACKDROP_IMAGE_NONE)
-        g_signal_emit(G_OBJECT(backdrop), backdrop_signals[BACKDROP_CYCLE], 0);
+        xfce_backdrop_cycle_backdrop(backdrop);
 
-    return TRUE;
+    /* Now to complicate things; we have to handle some special cases */
+    switch(backdrop->priv->cycle_period) {
+        case XFCE_BACKDROP_PERIOD_STARTUP:
+            /* no more cycling */
+            continue_cycling = FALSE;
+            break;
+
+        case XFCE_BACKDROP_PERIOD_CHRONOLOGICAL:
+        case XFCE_BACKDROP_PERIOD_HOURLY:
+            local_time = g_date_time_new_now_local();
+            minute = g_date_time_get_minute(local_time);
+            second = g_date_time_get_second(local_time);
+
+            /* find out how long until the next hour so we cycle on the hour */
+            cycle_interval = ((59 - minute) * 60) + (60 - second);
+
+            /* We created a new instance, kill this one */
+            continue_cycling = FALSE;
+            break;
+
+        case XFCE_BACKDROP_PERIOD_DAILY:
+            local_time = g_date_time_new_now_local();
+            hour   = g_date_time_get_hour  (local_time);
+            minute = g_date_time_get_minute(local_time);
+            second = g_date_time_get_second(local_time);
+
+            /* find out how long until the next day so we cycle on the day */
+            cycle_interval = ((23 - hour) * 60 * 60) + ((59 - minute) * 60) + (60 - second);
+
+            /* We created a new instance, kill this one */
+            continue_cycling = FALSE;
+            break;
+
+        default:
+            /* no changes required */
+            break;
+    }
+
+    /* Update the timer if we're trying to keep things on the hour/day */
+    if(cycle_interval != 0) {
+        DBG("calling g_timeout_add_seconds, interval is %d", cycle_interval);
+        backdrop->priv->cycle_timer_id = g_timeout_add_seconds(cycle_interval,
+                                                               (GSourceFunc)xfce_backdrop_timer,
+                                                               backdrop);
+    }
+
+    if(local_time != NULL)
+        g_date_time_unref(local_time);
+
+    return continue_cycling;
 }
 
 /**
  * xfce_backdrop_set_cycle_timer:
  * @backdrop: An #XfceBackdrop.
- * @cycle_timer: The amount of time, in minutes, to wait before changing the
- *               background image.
+ * @cycle_timer: The amount of time, based on the cycle_period, to wait before
+ *               changing the background image.
  *
  * If cycle_backdrop is enabled then this function will change the backdrop
- * image based on the cycle_timer, a value between 0 and G_MAXUSHORT.
- * A value of 0 indicates that the backdrop should not be changed.
+ * image based on the cycle_timer and cycle_period. The cycle_timer is a value
+ * between 0 and G_MAXUSHORT where a value of 0 indicates that the backdrop
+ * should not be changed.
  **/
 void
 xfce_backdrop_set_cycle_timer(XfceBackdrop *backdrop, guint cycle_timer)
 {
+    GDateTime *local_time = NULL;
+    guint cycle_interval;
+    gint hour, minute, second;
+
     g_return_if_fail(XFCE_IS_BACKDROP(backdrop));
 
     TRACE("entering, cycle_timer = %d", cycle_timer);
 
+    /* Sanity check to help prevent overflows */
     if(cycle_timer > G_MAXUSHORT)
         cycle_timer = G_MAXUSHORT;
 
     backdrop->priv->cycle_timer = cycle_timer;
 
+    /* always remove the old timer */
     if(backdrop->priv->cycle_timer_id != 0) {
         g_source_remove(backdrop->priv->cycle_timer_id);
         backdrop->priv->cycle_timer_id = 0;
     }
 
-    if(backdrop->priv->cycle_timer != 0 &&
-       backdrop->priv->cycle_backdrop == TRUE) {
-        backdrop->priv->cycle_timer_id = g_timeout_add_seconds(backdrop->priv->cycle_timer * 60,
+    if(backdrop->priv->cycle_timer != 0 && backdrop->priv->cycle_backdrop == TRUE) {
+        switch(backdrop->priv->cycle_period) {
+            case XFCE_BACKDROP_PERIOD_SECONDS:
+                cycle_interval = backdrop->priv->cycle_timer;
+                break;
+
+            case XFCE_BACKDROP_PERIOD_MINUES:
+                cycle_interval = backdrop->priv->cycle_timer * 60;
+                break;
+
+            case XFCE_BACKDROP_PERIOD_HOURS:
+                cycle_interval = backdrop->priv->cycle_timer * 60 * 60;
+                break;
+
+            case XFCE_BACKDROP_PERIOD_STARTUP:
+                cycle_interval = 1;
+                break;
+
+            case XFCE_BACKDROP_PERIOD_CHRONOLOGICAL:
+            case XFCE_BACKDROP_PERIOD_HOURLY:
+                local_time = g_date_time_new_now_local();
+                minute = g_date_time_get_minute(local_time);
+                second = g_date_time_get_second(local_time);
+
+                /* find out how long until the next hour so we cycle on the hour */
+                cycle_interval = ((59 - minute) * 60) + (60 - second);
+                break;
+
+            case XFCE_BACKDROP_PERIOD_DAILY:
+                local_time = g_date_time_new_now_local();
+                hour   = g_date_time_get_hour  (local_time);
+                minute = g_date_time_get_minute(local_time);
+                second = g_date_time_get_second(local_time);
+
+                /* find out how long until the next day so we cycle on the day */
+                cycle_interval = ((23 - hour) * 60 * 60) + ((59 - minute) * 60) + (60 - second);
+                break;
+
+            default:
+                g_critical("Unknown backdrop-cycle-period set");
+                break;
+            }
+
+        DBG("calling g_timeout_add_seconds, interval is %d", cycle_interval);
+        backdrop->priv->cycle_timer_id = g_timeout_add_seconds(cycle_interval,
                                                                (GSourceFunc)xfce_backdrop_timer,
                                                                backdrop);
     }
+
+    if(local_time != NULL)
+        g_date_time_unref(local_time);
 }
 
 guint
@@ -807,6 +1184,40 @@ xfce_backdrop_get_cycle_backdrop(XfceBackdrop *backdrop)
 }
 
 /**
+ * xfce_backdrop_set_cycle_period:
+ * @backdrop: An #XfceBackdrop.
+ * @period: Determines how often the backdrop will cycle.
+ *
+ * When cycling backdrops, the period setting will determine how fast the timer
+ * will fire (seconds vs minutes) or if the periodic backdrop will be based on
+ * actual wall clock values or just at xfdesktop's start up.
+ **/
+void
+xfce_backdrop_set_cycle_period(XfceBackdrop *backdrop,
+                               XfceBackdropCyclePeriod period)
+{
+    g_return_if_fail(XFCE_IS_BACKDROP(backdrop));
+    g_return_if_fail(period != XFCE_BACKDROP_PERIOD_INVALID);
+
+    TRACE("entering");
+
+    if(backdrop->priv->cycle_period != period) {
+        backdrop->priv->cycle_period = period;
+        /* Start or stop the backdrop changing */
+        xfce_backdrop_set_cycle_timer(backdrop,
+                                      xfce_backdrop_get_cycle_timer(backdrop));
+    }
+}
+
+XfceBackdropCyclePeriod
+xfce_backdrop_get_cycle_period(XfceBackdrop *backdrop)
+{
+    g_return_val_if_fail(XFCE_IS_BACKDROP(backdrop), XFCE_BACKDROP_PERIOD_INVALID);
+
+    return backdrop->priv->cycle_period;
+}
+
+/**
  * xfce_backdrop_set_random_order:
  * @backdrop: An #XfceBackdrop.
  * @random_order: When TRUE and the backdrops are set to cycle, a random image
@@ -835,6 +1246,8 @@ xfce_backdrop_get_random_order(XfceBackdrop *backdrop)
     return backdrop->priv->random_backdrop_order;
 }
 
+/* Generates the background that will either be displayed or will have the
+ * image drawn on top of */
 static GdkPixbuf *
 xfce_backdrop_generate_canvas(XfceBackdrop *backdrop)
 {
@@ -1215,6 +1628,9 @@ xfce_backdrop_file_ready_cb(GObject *source_object,
 
     TRACE("entering");
 
+    /* Finished with the file, clean it up */
+    g_object_unref(file);
+
     /* If this fails then close the loader, it will only display the selected
      * backdrop color */
     if(input_stream == NULL) {
diff --git a/src/xfce-backdrop.h b/src/xfce-backdrop.h
index 8a46927..85707ae 100644
--- a/src/xfce-backdrop.h
+++ b/src/xfce-backdrop.h
@@ -59,6 +59,18 @@ typedef enum
     XFCE_BACKDROP_COLOR_TRANSPARENT,
 } XfceBackdropColorStyle;
 
+typedef enum
+{
+    XFCE_BACKDROP_PERIOD_INVALID = -1,
+    XFCE_BACKDROP_PERIOD_SECONDS = 0,
+    XFCE_BACKDROP_PERIOD_MINUES,
+    XFCE_BACKDROP_PERIOD_HOURS,
+    XFCE_BACKDROP_PERIOD_STARTUP,
+    XFCE_BACKDROP_PERIOD_HOURLY,
+    XFCE_BACKDROP_PERIOD_DAILY,
+    XFCE_BACKDROP_PERIOD_CHRONOLOGICAL,
+} XfceBackdropCyclePeriod;
+
 struct _XfceBackdrop
 {
     GObject gobject;
@@ -118,6 +130,11 @@ void xfce_backdrop_set_cycle_backdrop    (XfceBackdrop *backdrop,
                                           gboolean cycle_backdrop);
 gboolean xfce_backdrop_get_cycle_backdrop(XfceBackdrop *backdrop);
 
+void xfce_backdrop_set_cycle_period      (XfceBackdrop *backdrop,
+                                          XfceBackdropCyclePeriod period);
+XfceBackdropCyclePeriod xfce_backdrop_get_cycle_period
+                                         (XfceBackdrop *backdrop);
+
 void xfce_backdrop_set_cycle_timer       (XfceBackdrop *backdrop,
                                           guint cycle_timer);
 guint xfce_backdrop_get_cycle_timer      (XfceBackdrop *backdrop);
diff --git a/src/xfce-desktop.c b/src/xfce-desktop.c
index b5b718d..d59a92a 100644
--- a/src/xfce-desktop.c
+++ b/src/xfce-desktop.c
@@ -245,9 +245,10 @@ xfce_desktop_setup_icon_view(XfceDesktop *desktop)
         xfce_desktop_ensure_system_font_size(desktop);
         
         desktop->priv->icon_view = xfdesktop_icon_view_new(manager);
+        /* If the user set a custom font size, use it. Otherwise use the system
+         * font size */
         xfdesktop_icon_view_set_font_size(XFDESKTOP_ICON_VIEW(desktop->priv->icon_view),
-                                          (!desktop->priv->icons_font_size_set
-                                           || !desktop->priv->icons_font_size)
+                                          (!desktop->priv->icons_font_size_set)
                                           ? desktop->priv->system_font_size
                                           : desktop->priv->icons_font_size);
         if(desktop->priv->icons_size > 0) {
@@ -365,7 +366,10 @@ backdrop_changed_cb(XfceBackdrop *backdrop, gpointer user_data)
     GdkRectangle rect;
     GdkRegion *clip_region = NULL;
     gint i, monitor = -1, current_workspace;
-    
+#ifdef G_ENABLE_DEBUG
+    gchar *monitor_name = NULL;
+#endif
+
     TRACE("entering");
     
     g_return_if_fail(XFCE_IS_DESKTOP(desktop));
@@ -394,9 +398,13 @@ backdrop_changed_cb(XfceBackdrop *backdrop, gpointer user_data)
     if(monitor == -1)
         return;
 
+#ifdef G_ENABLE_DEBUG
+    monitor_name = gdk_screen_get_monitor_plug_name(gscreen, monitor);
+
+    DBG("backdrop changed for workspace %d, monitor %d (%s)", current_workspace, monitor, monitor_name);
 
-    DBG("backdrop changed for workspace %d, monitor %d (%s)",
-        current_workspace, monitor, gdk_screen_get_monitor_plug_name(gscreen, monitor));
+    g_free(monitor_name);
+#endif
 
     if(xfce_desktop_get_n_monitors(desktop) > 1
        && xfce_workspace_get_xinerama_stretch(desktop->priv->workspaces[current_workspace])) {
@@ -818,7 +826,7 @@ xfce_desktop_class_init(XfceDesktopClass *klass)
                                     g_param_spec_uint("icon-font-size",
                                                       "icon font size",
                                                       "icon font size",
-                                                      4, 144, 12,
+                                                      0, 144, 12,
                                                       XFDESKTOP_PARAM_FLAGS));
 
     g_object_class_install_property(gobject_class, PROP_ICON_FONT_SIZE_SET,
@@ -863,7 +871,7 @@ static void
 xfce_desktop_finalize(GObject *object)
 {
     XfceDesktop *desktop = XFCE_DESKTOP(object);
-    
+
     g_object_unref(G_OBJECT(desktop->priv->channel));
     g_free(desktop->priv->property_prefix);
 
@@ -1054,14 +1062,13 @@ xfce_desktop_unrealize(GtkWidget *widget)
     gchar property_name[128];
     
     g_return_if_fail(XFCE_IS_DESKTOP(desktop));
-    
-    if(gtk_major_version > 2
-       || (gtk_major_version == 2 && gtk_minor_version >= 13))
-    {
-        g_signal_handlers_disconnect_by_func(G_OBJECT(desktop->priv->gscreen),
-                                             G_CALLBACK(xfce_desktop_monitors_changed),
-                                             desktop);
-    }
+
+    /* disconnect all the xfconf settings to this desktop */
+    xfconf_g_property_unbind_all(G_OBJECT(desktop));
+
+    g_signal_handlers_disconnect_by_func(G_OBJECT(desktop->priv->gscreen),
+                                         G_CALLBACK(xfce_desktop_monitors_changed),
+                                         desktop);
     
     if(gtk_widget_get_mapped(widget))
         gtk_widget_unmap(widget);
diff --git a/src/xfce-workspace.c b/src/xfce-workspace.c
index 936b960..68339ef 100644
--- a/src/xfce-workspace.c
+++ b/src/xfce-workspace.c
@@ -129,35 +129,61 @@ xfce_workspace_get_xinerama_stretch(XfceWorkspace *workspace)
 }
 
 static void
-backdrop_cycle_cb(XfceBackdrop *backdrop, gpointer user_data)
+xfce_workspace_change_backdrop(XfceWorkspace *workspace,
+                               XfceBackdrop *backdrop,
+                               const gchar *backdrop_file)
 {
-    const gchar* backdrop_file;
-    gchar *new_backdrop = NULL;
-    XfceWorkspace *workspace = XFCE_WORKSPACE(user_data);
+    XfconfChannel *channel = workspace->priv->channel;
+    char buf[1024];
+    gchar *monitor_name = NULL;
+    guint i, monitor_num;
 
-    TRACE("entering");
+    g_return_if_fail(workspace->priv->nbackdrops > 0);
 
-    g_return_if_fail(XFCE_IS_BACKDROP(backdrop));
+    TRACE("entering");
 
-    backdrop_file = xfce_backdrop_get_image_filename(backdrop);
+    /* Find out which monitor we're on */
+    for(i = 0; i < workspace->priv->nbackdrops; ++i) {
+        if(backdrop == workspace->priv->backdrops[i]) {
+            monitor_num = i;
+            break;
+        }
+    }
 
-    if(backdrop_file == NULL)
-        return;
+    monitor_name = gdk_screen_get_monitor_plug_name(workspace->priv->gscreen,
+                                                    monitor_num);
 
-    if(xfce_backdrop_get_random_order(backdrop)) {
-        DBG("Random! current file: %s", backdrop_file);
-        new_backdrop = xfdesktop_backdrop_choose_random(backdrop_file);
+    /* Get the backdrop's image property */
+    if(monitor_name == NULL) {
+        g_snprintf(buf, sizeof(buf), "%smonitor%d/workspace%d/last-image",
+                   workspace->priv->property_prefix, monitor_num, workspace->priv->workspace_num);
     } else {
-        DBG("Next! current file: %s", backdrop_file);
-        new_backdrop = xfdesktop_backdrop_choose_next(backdrop_file);
-    }
-    DBG("new file: %s for Workspace %d", new_backdrop,
-        xfce_workspace_get_workspace_num(workspace));
+        g_snprintf(buf, sizeof(buf), "%smonitor%s/workspace%d/last-image",
+                   workspace->priv->property_prefix, monitor_name, workspace->priv->workspace_num);
 
-    if(g_strcmp0(backdrop_file, new_backdrop) != 0) {
-        xfce_backdrop_set_image_filename(backdrop, new_backdrop);
-        g_free(new_backdrop);
+        g_free(monitor_name);
     }
+
+    /* Update the property so that xfdesktop won't show the same image every
+     * time it starts up when the user wants it to cycle different images */
+    xfconf_channel_set_string(channel, buf, backdrop_file);
+}
+
+static void
+backdrop_cycle_cb(XfceBackdrop *backdrop, gpointer user_data)
+{
+    XfceWorkspace *workspace = XFCE_WORKSPACE(user_data);
+    const gchar *new_backdrop;
+
+    TRACE("entering");
+
+    g_return_if_fail(XFCE_IS_BACKDROP(backdrop));
+
+    new_backdrop = xfce_backdrop_get_image_filename(backdrop);
+
+    /* update the xfconf property */
+    if(new_backdrop != NULL)
+        xfce_workspace_change_backdrop(workspace, backdrop, new_backdrop);
 }
 
 static void
@@ -452,8 +478,8 @@ xfce_workspace_migrate_backdrop_image_style(XfceWorkspace *workspace,
         xfce_backdrop_set_image_style(backdrop, style);
         g_value_unset(&value);
     } else {
-    /* If no value was ever set default to stretched */
-    xfce_backdrop_set_image_style(backdrop, XFCE_BACKDROP_IMAGE_STRETCHED);
+        /* If no value was ever set default to stretched */
+        xfce_backdrop_set_image_style(backdrop, XFCE_BACKDROP_IMAGE_STRETCHED);
     }
 }
 
@@ -507,6 +533,11 @@ xfce_workspace_connect_backdrop_settings(XfceWorkspace *workspace,
                            G_OBJECT(backdrop), "backdrop-cycle-enable");
 
     buf[pp_len] = 0;
+    g_strlcat(buf, "backdrop-cycle-period", sizeof(buf));
+    xfconf_g_property_bind(channel, buf, XFCE_TYPE_BACKDROP_CYCLE_PERIOD,
+                           G_OBJECT(backdrop), "backdrop-cycle-period");
+
+    buf[pp_len] = 0;
     g_strlcat(buf, "backdrop-cycle-timer", sizeof(buf));
     xfconf_g_property_bind(channel, buf, G_TYPE_UINT,
                            G_OBJECT(backdrop), "backdrop-cycle-timer");
diff --git a/src/xfdesktop-file-icon-manager.c b/src/xfdesktop-file-icon-manager.c
index efed03a..63d00c4 100644
--- a/src/xfdesktop-file-icon-manager.c
+++ b/src/xfdesktop-file-icon-manager.c
@@ -79,13 +79,7 @@
 #define SAVE_DELAY 7000
 #define BORDER     8
 
-#define SETTING_SHOW_FILESYSTEM  "/desktop-icons/file-icons/show-filesystem"
-#define SETTING_SHOW_HOME        "/desktop-icons/file-icons/show-home"
-#define SETTING_SHOW_TRASH       "/desktop-icons/file-icons/show-trash"
-#define SETTING_SHOW_REMOVABLE   "/desktop-icons/file-icons/show-removable"
-#define SETTING_SHOW_THUMBNAILS  "/desktop-icons/show-thumbnails"
-
-enum
+typedef enum
 {
     PROP0 = 0,
     PROP_FOLDER,
@@ -93,8 +87,11 @@ enum
     PROP_SHOW_HOME,
     PROP_SHOW_TRASH,
     PROP_SHOW_REMOVABLE,
+    PROP_SHOW_NETWORK_VOLUME,
+    PROP_SHOW_DEVICE_VOLUME,
+    PROP_SHOW_UNKNOWN_VOLUME,
     PROP_SHOW_THUMBNAILS
-};
+} XfdesktopFileIconManagerProp;
 
 struct _XfdesktopFileIconManagerPrivate
 {
@@ -122,6 +119,9 @@ struct _XfdesktopFileIconManagerPrivate
     GHashTable *special_icons;
     
     gboolean show_removable_media;
+    gboolean show_network_volumes;
+    gboolean show_device_volumes;
+    gboolean show_unknown_volumes;
     gboolean show_special[XFDESKTOP_SPECIAL_FILE_ICON_TRASH+1];
     gboolean show_thumbnails;
     
@@ -188,6 +188,16 @@ static void xfdesktop_file_icon_manager_load_desktop_folder(XfdesktopFileIconMan
 static void xfdesktop_file_icon_manager_load_removable_media(XfdesktopFileIconManager *fmanager);
 static void xfdesktop_file_icon_manager_remove_removable_media(XfdesktopFileIconManager *fmanager);
 
+
+static void xfdesktop_file_icon_manager_set_show_special_file(XfdesktopFileIconManager *manager,
+                                                              XfdesktopSpecialFileIconType type,
+                                                              gboolean show_special_file);
+static void xfdesktop_file_icon_manager_set_show_thumbnails(XfdesktopFileIconManager *manager,
+                                                            gboolean show_thumbnails);
+static void xfdesktop_file_icon_manager_set_show_removable_media(XfdesktopFileIconManager *manager,
+                                                                 XfdesktopFileIconManagerProp prop,
+                                                                 gboolean show);
+
 static void xfdesktop_file_icon_position_changed(XfdesktopFileIcon *icon,
                                                  gpointer user_data);
 
@@ -284,6 +294,24 @@ xfdesktop_file_icon_manager_class_init(XfdesktopFileIconManagerClass *klass)
                                                          "show removable",
                                                          TRUE,
                                                          XFDESKTOP_PARAM_FLAGS));
+    g_object_class_install_property(gobject_class, PROP_SHOW_NETWORK_VOLUME,
+                                    g_param_spec_boolean("show-network-volume",
+                                                         "show network volume",
+                                                         "show network volume",
+                                                         TRUE,
+                                                         XFDESKTOP_PARAM_FLAGS));
+    g_object_class_install_property(gobject_class, PROP_SHOW_DEVICE_VOLUME,
+                                    g_param_spec_boolean("show-device-volume",
+                                                         "show device volume",
+                                                         "show device volume",
+                                                         TRUE,
+                                                         XFDESKTOP_PARAM_FLAGS));
+    g_object_class_install_property(gobject_class, PROP_SHOW_UNKNOWN_VOLUME,
+                                    g_param_spec_boolean("show-unknown-volume",
+                                                         "show unknown volume",
+                                                         "show unknown volume",
+                                                         TRUE,
+                                                         XFDESKTOP_PARAM_FLAGS));
     g_object_class_install_property(gobject_class, PROP_SHOW_THUMBNAILS,
                                     g_param_spec_boolean("show-thumbnails",
                                                          "show-thumbnails",
@@ -347,7 +375,11 @@ xfdesktop_file_icon_manager_set_property(GObject *object,
             break;
 
         case PROP_SHOW_REMOVABLE:
+        case PROP_SHOW_NETWORK_VOLUME:
+        case PROP_SHOW_DEVICE_VOLUME:
+        case PROP_SHOW_UNKNOWN_VOLUME:
             xfdesktop_file_icon_manager_set_show_removable_media(fmanager,
+                                                                 property_id,
                                                                  g_value_get_boolean(value));
             break;
 
@@ -393,6 +425,18 @@ xfdesktop_file_icon_manager_get_property(GObject *object,
             g_value_set_boolean(value, fmanager->priv->show_removable_media);
             break;
 
+        case PROP_SHOW_NETWORK_VOLUME:
+            g_value_set_boolean(value, fmanager->priv->show_network_volumes);
+            break;
+
+        case PROP_SHOW_DEVICE_VOLUME:
+            g_value_set_boolean(value, fmanager->priv->show_device_volumes);
+            break;
+
+        case PROP_SHOW_UNKNOWN_VOLUME:
+            g_value_set_boolean(value, fmanager->priv->show_unknown_volumes);
+            break;
+
         case PROP_SHOW_THUMBNAILS:
             g_value_set_boolean(value, fmanager->priv->show_thumbnails);
             break;
@@ -1983,11 +2027,18 @@ xfdesktop_file_icon_manager_queue_thumbnail(XfdesktopFileIconManager *fmanager,
                 GFile *temp = g_file_new_for_path(thumbnail_file);
                 xfdesktop_icon_set_thumbnail_file(XFDESKTOP_ICON(icon), temp);
             }
+
+            g_free(thumbnail_file);
         } else {
             xfdesktop_thumbnailer_queue_thumbnail(fmanager->priv->thumbnailer,
                                                   path);
         }
     }
+
+    if(path) {
+        g_free(path);
+        path = NULL;
+    }
 }
 
 /* Adds a single icon to the icon view, popping from the top of the stack.
@@ -2160,9 +2211,33 @@ xfdesktop_file_icon_manager_add_volume_icon(XfdesktopFileIconManager *fmanager,
                                             GVolume *volume)
 {
     XfdesktopVolumeIcon *icon;
+    gchar *volume_type;
     
     g_return_val_if_fail(fmanager && G_IS_VOLUME(volume), NULL);
-    
+
+    /* If we aren't showing any media exit now */
+    if(!fmanager->priv->show_removable_media)
+        return NULL;
+
+    volume_type = g_volume_get_identifier(volume, G_VOLUME_IDENTIFIER_KIND_CLASS);
+
+    /* Check if we should filter out the volume icon based on what kind it is */
+    if(g_strcmp0(volume_type, "network") == 0 && !fmanager->priv->show_network_volumes) {
+        g_free(volume_type);
+        return NULL;
+    }
+    if(g_strcmp0(volume_type, "device") == 0 && !fmanager->priv->show_device_volumes) {
+        g_free(volume_type);
+        return NULL;
+    }
+    if(volume_type == NULL && !fmanager->priv->show_unknown_volumes) {
+        g_free(volume_type);
+        return NULL;
+    }
+
+    if(volume_type)
+        g_free(volume_type);
+
     /* should never return NULL */
     icon = xfdesktop_volume_icon_new(volume, fmanager->priv->gscreen);
 
@@ -2620,6 +2695,8 @@ xfdesktop_file_icon_manager_files_ready(GFileEnumerator *enumerator,
             g_signal_connect(fmanager->priv->metadata_monitor, "changed",
                              G_CALLBACK(xfdesktop_file_icon_manager_metadata_changed),
                              fmanager);
+
+            g_object_unref(metadata_location);
             g_free(location);
         }
     } else {
@@ -2703,38 +2780,11 @@ xfdesktop_file_icon_manager_clipboard_changed(XfdesktopClipboardManager *cmanage
                          cmanager);
 }
 
-
-static void
-xfdesktop_file_icon_manager_volume_changed(GVolume *volume,
-                                           gpointer user_data)
-{
-    XfdesktopFileIconManager *fmanager = XFDESKTOP_FILE_ICON_MANAGER(user_data);
-    XfdesktopIcon *icon;
-    gboolean is_present = xfdesktop_file_utils_volume_is_present(volume);
-    
-    icon = g_hash_table_lookup(fmanager->priv->removable_icons, volume);
-
-    if(is_present && !icon)
-        xfdesktop_file_icon_manager_add_volume_icon(fmanager, volume);
-    else if(!is_present && icon) {
-        xfdesktop_icon_view_remove_item(fmanager->priv->icon_view, icon);
-        g_hash_table_remove(fmanager->priv->removable_icons, volume);
-    }
-}
-
 static void
 xfdesktop_file_icon_manager_add_removable_volume(XfdesktopFileIconManager *fmanager,
                                                  GVolume *volume)
 {
-    if(!xfdesktop_file_utils_volume_is_removable(volume))
-        return;
-    
-    if(xfdesktop_file_utils_volume_is_present(volume))
-        xfdesktop_file_icon_manager_add_volume_icon(fmanager, volume);
-    
-    g_signal_connect(G_OBJECT(volume), "changed",
-                     G_CALLBACK(xfdesktop_file_icon_manager_volume_changed),
-                     fmanager);
+    xfdesktop_file_icon_manager_add_volume_icon(fmanager, volume);
 }
 
 static void
@@ -2766,11 +2816,11 @@ static void
 xfdesktop_file_icon_manager_load_removable_media(XfdesktopFileIconManager *fmanager)
 {
     GList *volumes, *l;
-    
+
     /* ensure we don't re-enter if we're already set up */
     if(fmanager->priv->removable_icons)
         return;
-    
+
     if(!fmanager->priv->volume_monitor)
         fmanager->priv->volume_monitor = g_volume_monitor_get();
     
@@ -2801,14 +2851,6 @@ xfdesktop_file_icon_manager_ht_remove_removable_media(gpointer key,
 {
     XfdesktopIcon *icon = XFDESKTOP_ICON(value);
     XfdesktopFileIconManager *fmanager = XFDESKTOP_FILE_ICON_MANAGER(user_data);
-    GVolume *volume;
-
-    volume = xfdesktop_volume_icon_peek_volume(XFDESKTOP_VOLUME_ICON(icon));
-    if(volume) {
-        g_signal_handlers_disconnect_by_func(volume,
-                                             G_CALLBACK(xfdesktop_file_icon_manager_volume_changed),
-                                             fmanager);
-    }
     
     xfdesktop_icon_view_remove_item(fmanager->priv->icon_view, icon);
 }
@@ -3546,46 +3588,73 @@ xfdesktop_file_icon_manager_new(GFile *folder,
                             NULL);
     fmanager->priv->channel = g_object_ref(G_OBJECT(channel));
 
-    xfconf_g_property_bind(channel, SETTING_SHOW_FILESYSTEM, G_TYPE_BOOLEAN,
+    xfconf_g_property_bind(channel, DESKTOP_ICONS_SHOW_FILESYSTEM, G_TYPE_BOOLEAN,
                            G_OBJECT(fmanager), "show-filesystem");
-    xfconf_g_property_bind(channel, SETTING_SHOW_HOME, G_TYPE_BOOLEAN,
+    xfconf_g_property_bind(channel, DESKTOP_ICONS_SHOW_HOME, G_TYPE_BOOLEAN,
                            G_OBJECT(fmanager), "show-home");
-    xfconf_g_property_bind(channel, SETTING_SHOW_TRASH, G_TYPE_BOOLEAN,
+    xfconf_g_property_bind(channel, DESKTOP_ICONS_SHOW_TRASH, G_TYPE_BOOLEAN,
                            G_OBJECT(fmanager), "show-trash");
-    xfconf_g_property_bind(channel, SETTING_SHOW_REMOVABLE, G_TYPE_BOOLEAN,
+    xfconf_g_property_bind(channel, DESKTOP_ICONS_SHOW_REMOVABLE, G_TYPE_BOOLEAN,
                            G_OBJECT(fmanager), "show-removable");
-    xfconf_g_property_bind(channel, SETTING_SHOW_THUMBNAILS, G_TYPE_BOOLEAN,
+    xfconf_g_property_bind(channel, DESKTOP_ICONS_SHOW_NETWORK_REMOVABLE, G_TYPE_BOOLEAN,
+                           G_OBJECT(fmanager), "show-network-volume");
+    xfconf_g_property_bind(channel, DESKTOP_ICONS_SHOW_DEVICE_REMOVABLE, G_TYPE_BOOLEAN,
+                           G_OBJECT(fmanager), "show-device-volume");
+    xfconf_g_property_bind(channel, DESKTOP_ICONS_SHOW_UNKNWON_REMOVABLE, G_TYPE_BOOLEAN,
+                           G_OBJECT(fmanager), "show-unknown-volume");
+    xfconf_g_property_bind(channel, DESKTOP_ICONS_SHOW_THUMBNAILS, G_TYPE_BOOLEAN,
                            G_OBJECT(fmanager), "show-thumbnails");
 
     return XFDESKTOP_ICON_VIEW_MANAGER(fmanager);
 }
 
-void
+static void
 xfdesktop_file_icon_manager_set_show_removable_media(XfdesktopFileIconManager *manager,
-                                                     gboolean show_removable_media)
+                                                     XfdesktopFileIconManagerProp prop,
+                                                     gboolean show)
 {
     g_return_if_fail(XFDESKTOP_IS_FILE_ICON_MANAGER(manager));
-    
-    if(show_removable_media == manager->priv->show_removable_media)
-        return;
-    
-    manager->priv->show_removable_media = show_removable_media;
-    
+
+    switch(prop) {
+        case PROP_SHOW_REMOVABLE:
+            if(show == manager->priv->show_removable_media)
+                return;
+
+            manager->priv->show_removable_media = show;
+            break;
+        case PROP_SHOW_NETWORK_VOLUME:
+            if(show == manager->priv->show_network_volumes)
+                return;
+
+            manager->priv->show_network_volumes = show;
+            break;
+        case PROP_SHOW_DEVICE_VOLUME:
+            if(show == manager->priv->show_device_volumes)
+                return;
+
+            manager->priv->show_device_volumes = show;
+            break;
+        case PROP_SHOW_UNKNOWN_VOLUME:
+            if(show == manager->priv->show_unknown_volumes)
+                return;
+
+            manager->priv->show_unknown_volumes = show;
+            break;
+        default:
+            break;
+    }
+
     if(!manager->priv->inited)
         return;
-    
-    if(show_removable_media)
+
+    /* Always remove all the icons when a setting changes */
+    xfdesktop_file_icon_manager_remove_removable_media(manager);
+
+    /* Then re-add the icons the user wants */
+    if(manager->priv->show_removable_media)
         xfdesktop_file_icon_manager_load_removable_media(manager);
-    else
-        xfdesktop_file_icon_manager_remove_removable_media(manager);
 }
 
-gboolean
-xfdesktop_file_icon_manager_get_show_removable_media(XfdesktopFileIconManager *manager)
-{
-    g_return_val_if_fail(XFDESKTOP_IS_FILE_ICON_MANAGER(manager), FALSE);
-    return manager->priv->show_removable_media;
-}
 
 static void
 xfdesktop_file_icon_manager_requeue_thumbnails(gpointer key,
@@ -3608,7 +3677,7 @@ xfdesktop_file_icon_manager_remove_thumbnails(gpointer key,
     xfdesktop_icon_delete_thumbnail(XFDESKTOP_ICON(icon));
 }
 
-void
+static void
 xfdesktop_file_icon_manager_set_show_thumbnails(XfdesktopFileIconManager *manager,
                                                 gboolean show_thumbnails)
 {
@@ -3637,14 +3706,7 @@ xfdesktop_file_icon_manager_set_show_thumbnails(XfdesktopFileIconManager *manage
     }
 }
 
-gboolean
-xfdesktop_file_icon_manager_get_show_thumbnails(XfdesktopFileIconManager *manager)
-{
-    g_return_val_if_fail(XFDESKTOP_IS_FILE_ICON_MANAGER(manager), FALSE);
-    return manager->priv->show_thumbnails;
-}
-
-void
+static void
 xfdesktop_file_icon_manager_set_show_special_file(XfdesktopFileIconManager *manager,
                                                   XfdesktopSpecialFileIconType type,
                                                   gboolean show_special_file)
@@ -3675,17 +3737,6 @@ xfdesktop_file_icon_manager_set_show_special_file(XfdesktopFileIconManager *mana
     }
 }
 
-gboolean
-xfdesktop_file_icon_manager_get_show_special_file(XfdesktopFileIconManager *manager,
-                                                  XfdesktopSpecialFileIconType type)
-{
-    g_return_val_if_fail(XFDESKTOP_IS_FILE_ICON_MANAGER(manager), FALSE);
-    g_return_val_if_fail((int)type >= 0 && type <= XFDESKTOP_SPECIAL_FILE_ICON_TRASH,
-                         FALSE);
-    
-    return manager->priv->show_special[type];
-}
-
 static void
 xfdesktop_file_icon_manager_update_image(GtkWidget *widget,
                                          gchar *srcfile,
@@ -3705,6 +3756,8 @@ xfdesktop_file_icon_manager_update_image(GtkWidget *widget,
     {
         g_object_unref(file);
         file = g_file_new_for_path(thumbfile);
-        xfdesktop_icon_set_thumbnail_file(icon, file);
+        xfdesktop_icon_set_thumbnail_file(icon, g_object_ref(file));
     }
+
+    g_object_unref(file);
 }
diff --git a/src/xfdesktop-file-icon-manager.h b/src/xfdesktop-file-icon-manager.h
index 60fb0d0..847f573 100644
--- a/src/xfdesktop-file-icon-manager.h
+++ b/src/xfdesktop-file-icon-manager.h
@@ -55,19 +55,6 @@ GType xfdesktop_file_icon_manager_get_type(void) G_GNUC_CONST;
 XfdesktopIconViewManager *xfdesktop_file_icon_manager_new(GFile *folder,
                                                           XfconfChannel *channel);
 
-void xfdesktop_file_icon_manager_set_show_removable_media(XfdesktopFileIconManager *manager,
-                                                          gboolean show_removable_media);
-gboolean xfdesktop_file_icon_manager_get_show_removable_media(XfdesktopFileIconManager *manager);
-
-void xfdesktop_file_icon_manager_set_show_special_file(XfdesktopFileIconManager *manager,
-                                                       XfdesktopSpecialFileIconType type,
-                                                       gboolean show_special_file);
-gboolean xfdesktop_file_icon_manager_get_show_special_file(XfdesktopFileIconManager *manager,
-                                                           XfdesktopSpecialFileIconType type);
-void xfdesktop_file_icon_manager_set_show_thumbnails(XfdesktopFileIconManager *manager,
-                                                     gboolean show_thumbnails);
-gboolean xfdesktop_file_icon_manager_get_show_thumbnails(XfdesktopFileIconManager *manager);
-
 gboolean xfdesktop_file_icon_manager_get_cached_icon_position(
                                                     XfdesktopFileIconManager *fmanager,
                                                     const gchar *name,
diff --git a/src/xfdesktop-file-utils.c b/src/xfdesktop-file-utils.c
index 44feba1..4f53c57 100644
--- a/src/xfdesktop-file-utils.c
+++ b/src/xfdesktop-file-utils.c
@@ -237,137 +237,6 @@ xfdesktop_file_utils_get_display_name(GFile *file,
     return display_name;
 }
 
-gboolean
-xfdesktop_file_utils_volume_is_present(GVolume *volume)
-{
-    gboolean has_media = FALSE;
-    gboolean is_shadowed = FALSE;
-    GDrive *drive;
-#if GLIB_CHECK_VERSION (2, 20, 0)
-    GMount *mount;
-#endif
-
-    g_return_val_if_fail(G_IS_VOLUME(volume), FALSE);
-
-    drive = g_volume_get_drive (volume);
-    if(drive) {
-        has_media = g_drive_has_media(drive);
-        g_object_unref(drive);
-    }
-
-#if GLIB_CHECK_VERSION (2, 20, 0)
-    mount = g_volume_get_mount(volume);
-    if(mount) {
-        is_shadowed = g_mount_is_shadowed(mount);
-        g_object_unref(mount);
-    }
-#endif
-
-    return has_media && !is_shadowed;
-}
-
-#ifdef HAVE_GIO_UNIX
-static gboolean
-xfdesktop_file_utils_mount_is_internal (GMount *mount)
-{
-    const gchar *point_mount_path;
-    gboolean is_internal = FALSE;
-    GFile *root;
-    GList *lp;
-    GList *mount_points;
-    gchar *mount_path;
-
-    g_return_val_if_fail(G_IS_MOUNT(mount), FALSE);
-
-    /* determine the mount path */
-    root = g_mount_get_root(mount);
-    mount_path = g_file_get_path(root);
-    g_object_unref(root);
-
-    /* assume non-internal if we cannot determine the path */
-    if (!mount_path)
-        return FALSE;
-
-    if (g_unix_is_mount_path_system_internal(mount_path)) {
-        /* mark as internal */
-        is_internal = TRUE;
-    } else {
-        /* get a list of all mount points */
-        mount_points = g_unix_mount_points_get(NULL);
-
-        /* search for the mount point associated with the mount entry */
-        for (lp = mount_points; !is_internal && lp != NULL; lp = lp->next) {
-            point_mount_path = g_unix_mount_point_get_mount_path(lp->data);
-
-            /* check if this is the mount point we are looking for */
-            if (g_strcmp0(mount_path, point_mount_path) == 0) {
-                /* mark as internal if the user cannot mount this device */
-                if (!g_unix_mount_point_is_user_mountable(lp->data))
-                    is_internal = TRUE;
-            }
-
-            /* free the mount point, we no longer need it */
-            g_unix_mount_point_free(lp->data);
-        }
-
-        /* free the mount point list */
-        g_list_free(mount_points);
-    }
-
-    g_free(mount_path);
-
-    return is_internal;
-}
-#endif
-
-
-
-gboolean
-xfdesktop_file_utils_volume_is_removable(GVolume *volume)
-{
-  gboolean can_eject;
-  gboolean can_mount = FALSE;
-  gboolean can_unmount = FALSE;
-  gboolean is_removable = FALSE;
-  gboolean is_internal = FALSE;
-  GDrive *drive;
-  GMount *mount;
-
-  g_return_val_if_fail(G_IS_VOLUME(volume), FALSE);
-
-  /* check if the volume can be ejected */
-  can_eject = g_volume_can_eject(volume);
-
-  /* determine the drive for the volume */
-  drive = g_volume_get_drive(volume);
-  if(drive) {
-      /*check if the drive media can be removed */
-      is_removable = g_drive_is_media_removable(drive);
-
-      /* release the drive */
-      g_object_unref(drive);
-  }
-
-  /* determine the mount for the volume (if it is mounted at all) */
-  mount = g_volume_get_mount(volume);
-  if(mount) {
-#ifdef HAVE_GIO_UNIX
-      is_internal = xfdesktop_file_utils_mount_is_internal (mount);
-#endif
-
-      /* check if the volume can be unmounted */
-      can_unmount = g_mount_can_unmount(mount);
-
-      /* release the mount */
-      g_object_unref(mount);
-  }
-
-  /* determine whether the device can be mounted */
-  can_mount = g_volume_can_mount(volume);
-
-  return (!is_internal) && (can_eject || can_unmount || is_removable || can_mount);
-}
-
 GList *
 xfdesktop_file_utils_file_icon_list_to_file_list(GList *icon_list)
 {
diff --git a/src/xfdesktop-file-utils.h b/src/xfdesktop-file-utils.h
index 65bb9bc..a3fed69 100644
--- a/src/xfdesktop-file-utils.h
+++ b/src/xfdesktop-file-utils.h
@@ -39,9 +39,6 @@ GKeyFile *xfdesktop_file_utils_query_key_file(GFile *file,
 gchar *xfdesktop_file_utils_get_display_name(GFile *file,
                                              GFileInfo *info);
 
-gboolean xfdesktop_file_utils_volume_is_present(GVolume *volume);
-gboolean xfdesktop_file_utils_volume_is_removable(GVolume *volume);
-
 GList *xfdesktop_file_utils_file_icon_list_to_file_list(GList *icon_list);
 GList *xfdesktop_file_utils_file_list_from_string(const gchar *string);
 gchar *xfdesktop_file_utils_file_list_to_string(GList *file_list);
diff --git a/src/xfdesktop-icon-view.c b/src/xfdesktop-icon-view.c
index 817db45..987c9a7 100644
--- a/src/xfdesktop-icon-view.c
+++ b/src/xfdesktop-icon-view.c
@@ -52,8 +52,10 @@
 #include <libxfce4ui/libxfce4ui.h>
 #include <xfconf/xfconf.h>
 
-#define DEFAULT_FONT_SIZE  12
-#define DEFAULT_ICON_SIZE  32
+#define DEFAULT_FONT_SIZE     12
+#define DEFAULT_ICON_SIZE     32
+#define DEFAULT_TOOLTIP_SIZE 128
+#define MAX_TOOLTIP_SIZE     512
 
 #define ICON_SIZE         (icon_view->priv->icon_size)
 #define TEXT_WIDTH        ((icon_view->priv->cell_text_width_proportion) * ICON_SIZE)
@@ -178,7 +180,13 @@ struct _XfdesktopIconViewPrivate
     gdouble cell_text_width_proportion;
 
     gboolean ellipsize_icon_labels;
-    guint    tooltip_size;
+
+    /* tooltip options - There's a style and an xfconf property.
+     * The order is xfconf, style, with a fall back of DEFAULT_TOOLTIP_SIZE.
+     * xfdesktop_icon_view_get_tooltip_size will return the correct size. */
+    gboolean show_tooltips;
+    gint   tooltip_size_from_style;
+    double tooltip_szie_from_xfconf;
 
     gboolean single_click;
 };
@@ -327,6 +335,7 @@ static gboolean xfdesktop_icon_view_icon_find_position(XfdesktopIconView *icon_v
 static gboolean xfdesktop_icon_view_shift_area_to_cell(XfdesktopIconView *icon_view,
                                                        XfdesktopIcon *icon,
                                                        GdkRectangle *text_area);
+static gint xfdesktop_icon_view_get_tooltip_size(XfdesktopIconView *icon_view);
 static gboolean xfdesktop_icon_view_show_tooltip(GtkWidget *widget,
                                                  gint x,
                                                  gint y,
@@ -361,6 +370,8 @@ enum
 {
     PROP_0 = 0,
     PROP_SINGLE_CLICK,
+    PROP_SHOW_TOOLTIPS,
+    PROP_TOOLTIP_SIZE,
 };
 
 
@@ -575,11 +586,11 @@ xfdesktop_icon_view_class_init(XfdesktopIconViewClass *klass)
                                                                 G_PARAM_READABLE));
 
     gtk_widget_class_install_style_property(widget_class,
-                                            g_param_spec_uint("tooltip-size",
-                                                              "Tooltip Image Size",
-                                                              "The size of the tooltip image preview",
-                                                              0, 512, 128,
-                                                              G_PARAM_READABLE));
+                                            g_param_spec_int("tooltip-size",
+                                                             "Tooltip Image Size",
+                                                             "The size of the tooltip image preview",
+                                                             -1, MAX_TOOLTIP_SIZE, -1,
+                                                             G_PARAM_READABLE));
 
 #define XFDESKTOP_PARAM_FLAGS  (G_PARAM_READWRITE \
                                 | G_PARAM_CONSTRUCT \
@@ -594,6 +605,20 @@ xfdesktop_icon_view_class_init(XfdesktopIconViewClass *klass)
                                                          FALSE,
                                                          XFDESKTOP_PARAM_FLAGS));
 
+    g_object_class_install_property(gobject_class, PROP_SHOW_TOOLTIPS,
+                                    g_param_spec_boolean("show-tooltips",
+                                                         "show tooltips",
+                                                         "show tooltips for icons on the desktop",
+                                                         TRUE,
+                                                         XFDESKTOP_PARAM_FLAGS));
+
+    g_object_class_install_property(gobject_class, PROP_TOOLTIP_SIZE,
+                                    g_param_spec_double("tooltip-size",
+                                                        "tooltip size",
+                                                        "size of the tooltip image preview",
+                                                        -1, MAX_TOOLTIP_SIZE, -1,
+                                                        XFDESKTOP_PARAM_FLAGS));
+
 #undef XFDESKTOP_PARAM_FLAGS
 
     /* same binding entries as GtkIconView */
@@ -726,6 +751,14 @@ xfce_icon_view_set_property(GObject *object,
             icon_view->priv->single_click = g_value_get_boolean (value);
             break;
 
+        case PROP_SHOW_TOOLTIPS:
+            icon_view->priv->show_tooltips = g_value_get_boolean(value);
+            break;
+
+        case PROP_TOOLTIP_SIZE:
+            icon_view->priv->tooltip_szie_from_xfconf = g_value_get_double(value);
+            break;
+
         default:
             G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
             break;
@@ -745,6 +778,14 @@ xfce_icon_view_get_property(GObject *object,
             g_value_set_boolean(value, icon_view->priv->single_click);
             break;
 
+        case PROP_SHOW_TOOLTIPS:
+            g_value_set_boolean(value, icon_view->priv->show_tooltips);
+            break;
+
+        case PROP_TOOLTIP_SIZE:
+            g_value_set_double(value, icon_view->priv->tooltip_szie_from_xfconf);
+            break;
+
         default:
             G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
             break;
@@ -922,6 +963,27 @@ xfdesktop_icon_view_get_single_click(XfdesktopIconView *icon_view)
     return icon_view->priv->single_click;
 }
 
+static gint
+xfdesktop_icon_view_get_tooltip_size(XfdesktopIconView *icon_view)
+{
+    g_return_val_if_fail(XFDESKTOP_IS_ICON_VIEW(icon_view), DEFAULT_TOOLTIP_SIZE);
+
+    /* Check if we're showing tooltips at all */
+    if(!icon_view->priv->show_tooltips)
+        return 0;
+
+    /* If the xfconf size is set and sane, use it */
+    if(icon_view->priv->tooltip_szie_from_xfconf >= 0)
+        return icon_view->priv->tooltip_szie_from_xfconf;
+
+    /* if the style size is set and sane, use it */
+    if(icon_view->priv->tooltip_size_from_style >= 0)
+        return icon_view->priv->tooltip_size_from_style;
+
+    /* Fall back */
+    return DEFAULT_TOOLTIP_SIZE;
+}
+
 static gboolean
 xfdesktop_icon_view_button_release(GtkWidget *widget,
                                    GdkEventButton *evt,
@@ -1091,24 +1153,31 @@ xfdesktop_icon_view_show_tooltip(GtkWidget *widget,
     XfdesktopIconView *icon_view = XFDESKTOP_ICON_VIEW(widget);
     const gchar *tip_text;
     gchar *padded_tip_text = NULL;
+    gint tooltip_size;
     
     if(!icon_view->priv->item_under_pointer
        || icon_view->priv->definitely_dragging)
     {
         return FALSE;
     }
-    
+
+    /* not showing tooltips */
+    if(!icon_view->priv->show_tooltips)
+        return FALSE;
+
+    tooltip_size = xfdesktop_icon_view_get_tooltip_size(icon_view);
+
     tip_text = xfdesktop_icon_peek_tooltip(icon_view->priv->item_under_pointer);
     if(!tip_text)
         return FALSE;
 
     padded_tip_text = g_strdup_printf("%s\t", tip_text);
 
-    if(icon_view->priv->tooltip_size > 0) {
+    if(tooltip_size > 0) {
         gtk_tooltip_set_icon(tooltip,
                 xfdesktop_icon_peek_tooltip_pixbuf(icon_view->priv->item_under_pointer,
-                                                   icon_view->priv->tooltip_size * 1.5f,
-                                                   icon_view->priv->tooltip_size));
+                                                   tooltip_size * 1.5f,
+                                                   tooltip_size));
     }
 
     gtk_tooltip_set_text(tooltip, padded_tip_text);
@@ -1884,7 +1953,7 @@ xfdesktop_icon_view_style_set(GtkWidget *widget,
                          "cell-padding", &icon_view->priv->cell_padding,
                          "cell-text-width-proportion", &icon_view->priv->cell_text_width_proportion,
                          "ellipsize-icon-labels", &icon_view->priv->ellipsize_icon_labels,
-                         "tooltip-size", &icon_view->priv->tooltip_size,
+                         "tooltip-size", &icon_view->priv->tooltip_size_from_style,
                          "label-radius", &icon_view->priv->label_radius,
                          NULL);
 
@@ -1892,7 +1961,7 @@ xfdesktop_icon_view_style_set(GtkWidget *widget,
     DBG("cell padding is %d", icon_view->priv->cell_padding);
     DBG("cell text width proportion is %f", icon_view->priv->cell_text_width_proportion);
     DBG("ellipsize icon label is %s", icon_view->priv->ellipsize_icon_labels?"true":"false");
-    DBG("tooltip size is %d", icon_view->priv->tooltip_size);
+    DBG("tooltip size is %d", icon_view->priv->tooltip_size_from_style);
     DBG("label radius is %f", icon_view->priv->label_radius);
 
     if(icon_view->priv->selection_box_color) {
@@ -3046,7 +3115,9 @@ xfdesktop_icon_view_paint_icon(XfdesktopIconView *icon_view,
     }
 
     /* Only redraw the text if the text area requires it.  */
-    if(gdk_rectangle_intersect(area, &text_extents, &intersection)) {
+    if(gdk_rectangle_intersect(area, &text_extents, &intersection)
+       && icon_view->priv->font_size > 0)
+    {
         xfdesktop_paint_rounded_box(icon_view, state, &text_extents, area);
 
         if (state == GTK_STATE_NORMAL) {
@@ -3596,6 +3667,18 @@ xfdesktop_icon_view_new(XfdesktopIconViewManager *manager)
                            G_TYPE_BOOLEAN,
                            G_OBJECT(icon_view),
                            "single_click");
+
+    xfconf_g_property_bind(icon_view->priv->channel,
+                           "/desktop-icons/show-tooltips",
+                           G_TYPE_BOOLEAN,
+                           G_OBJECT(icon_view),
+                           "show_tooltips");
+
+    xfconf_g_property_bind(icon_view->priv->channel,
+                           "/desktop-icons/tooltip-size",
+                           G_TYPE_DOUBLE,
+                           G_OBJECT(icon_view),
+                           "tooltip_size");
     
     return GTK_WIDGET(icon_view);
 }
diff --git a/src/xfdesktop-volume-icon.c b/src/xfdesktop-volume-icon.c
index c8170e8..a8427f1 100644
--- a/src/xfdesktop-volume-icon.c
+++ b/src/xfdesktop-volume-icon.c
@@ -1044,22 +1044,11 @@ 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


More information about the Xfce4-commits mailing list