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

Eric Koegel noreply at xfce.org
Sun Aug 4 10:36:30 CEST 2013


Updating branch refs/heads/master
         to bf859f1caef83338e4c5c5725b55009abe68457d (commit)
       from b54644715e6ff06af40559f2de9f7f4c5028e3ba (commit)

commit bf859f1caef83338e4c5c5725b55009abe68457d
Merge: b546447 799811c
Author: Eric Koegel <eric.koegel at gmail.com>
Date:   Sun Aug 4 11:33:51 2013 +0300

    Merge branch 'eric/wallpaper-and-settings-improvements'
    
    Conflicts:
    	src/xfce-backdrop.c
    
    Removed brightness code that was causing the conflict and isn't used anymore.

commit 799811c5b53c53552067af5418f2ae7b7ceddff9
Author: Eric Koegel <eric.koegel at gmail.com>
Date:   Tue Apr 30 19:01:31 2013 +0300

    Set the column spacing to 12

commit 13fd293590da7934f61bf59129080ec535b5b9d8
Author: Eric Koegel <eric.koegel at gmail.com>
Date:   Sat Apr 27 15:41:02 2013 +0300

    Fix memory leaks
    
    Use the destroy notify callback when adding items to remove duplicated
    code. Also found and fixed a couple memory leaks.

commit de3e0239693bbde88a32805541d5decdbef4b9b3
Author: Eric Koegel <eric.koegel at gmail.com>
Date:   Fri Apr 19 11:46:09 2013 +0300

    Use a collation key when sorting wallpapers

commit 066b3f13732fe54d2cf54cc031664a7b023235e0
Author: Eric Koegel <eric.koegel at gmail.com>
Date:   Fri Apr 12 14:50:36 2013 +0300

    Support xfdesktop-settings as a pinned window

commit b651fd1ebc1b4a93bb46c8dc265849a73155fe20
Author: Eric Koegel <eric.koegel at gmail.com>
Date:   Fri Apr 12 14:10:56 2013 +0300

    Change tooltips in xfdesktop-settings
    
    Since the tooltips were reporting the image size of the thumbnails
    and parsing the original file just to get the image dimensions is
    slow, this patch changes it to pull the content type and file size
    to populate the tooltip with. Also fixed how tooltips in the icon
    view popped up so that it follows the mouse when it is sensitive.

commit 520f3055a62a5c125be42127bd81a6bf705d760c
Author: Eric Koegel <eric.koegel at gmail.com>
Date:   Fri Apr 12 11:08:51 2013 +0300

    Change wallpaper iconview spacing and max width
    
    Changed the max aspect ratio of the xfdesktop-settings iconview
    so it would pack the images better. Removed some of the row and
    column spacing and increased the item-padding so that the selected
    item stands out better.

commit 9587dfd4a006c121ceceb068b969093956b24fc0
Author: Eric Koegel <eric.koegel at gmail.com>
Date:   Fri Apr 12 10:53:53 2013 +0300

    Align folder and color style combo boxes
    
    Packed the folder, color, and image styles into a GtkTable to
    align things better. Also removed some unneeded Gtk containers
    from the glade file and labeled the id's to be more descriptive.

commit 8b8cdbe39e3218eb59135681aae0f816849099f6
Author: Eric Koegel <eric.koegel at gmail.com>
Date:   Fri Apr 12 09:09:49 2013 +0300

    Change lable to read: Apply to all workspaces

commit 6d78e6bc921b4a4b408af0e6c94aaf682ea3c5fd
Author: Eric Koegel <eric.koegel at gmail.com>
Date:   Mon Apr 8 18:54:51 2013 +0300

    Update icon view frame name based on monitor count

commit 8385169faa534301b7131d842c062bb9971e5f67
Author: Eric Koegel <eric.koegel at gmail.com>
Date:   Sun Apr 7 11:11:13 2013 +0300

    Select wallpaper on loading
    
    Increases the icon view item padding size so the selected item stands out better.
    cb_folder_selection_change is manually called because GTK introduced a bug where
    changing the gtk file chooser folder in code no longer emits the correct signal.

commit 3ea195b2ac3223a4c2de1e7eeb30b3461eb4994e
Author: Eric Koegel <eric.koegel at gmail.com>
Date:   Sat Apr 6 15:45:38 2013 +0300

    xfdesktop-settings is more responsive
    
    Changed to using g_file_enumerate_children_async and enumerating
    each file individually in an idle callback function to keep things
    responsive while loading large directories of images. This is also
    cancellable so that when the user moves the window to a different
    monitor or workspace it will respond faster.

commit 4d154b0614252950576b4ec49f067102f729c796
Author: Eric Koegel <eric.koegel at gmail.com>
Date:   Sat Mar 30 13:37:15 2013 +0300

    Use an async message queue to load preview images
    
    This patch uses the g_async_queue for message passing between the
    main thread and the preview thread of the settings app. Doing this
    gets rid of the idle timeout callback and a seperate thread loading
    function. It also makes it easy to pop any pending previews when
    the app changes what the icon view should display.

commit 4e51013473eed4a9879267db7d48986061caddd9
Author: Eric Koegel <eric.koegel at gmail.com>
Date:   Sat Mar 30 10:08:50 2013 +0300

    Cache wallpapers when they are loaded
    
    This is to make workspace switching faster. It only cached when drawing the
    wallpaper because the user may have lots of workspaces configured for whatever
    reason and never use all of them, so this would save on the memory overhead.
    This patch also improves the backdrop comparison check and simplifies the
    unbinding of some settings.

commit bcd164f4e460f1cdaff1db4287a1109518f895e5
Author: Eric Koegel <eric.koegel at gmail.com>
Date:   Sat Mar 30 09:03:43 2013 +0300

    Respond to monitors-changed events

commit 9ca8aea6d217d72f95287b9750d152eca734a3eb
Author: Eric Koegel <eric.koegel at gmail.com>
Date:   Sun Mar 24 15:24:31 2013 +0300

    Remove unused code

commit be0719f7c9e686ee52dc8a9a37f27e15f18203d1
Author: Eric Koegel <eric.koegel at gmail.com>
Date:   Sun Mar 24 15:07:29 2013 +0300

    Fix for invalid single workspace number in settings app
    
    Xfdesktop-settings app now repsonds to workspaces being created
    and destroyed because it can impact how the single workspace mode
    operates. If the single workspace number is set to a workspace that
    is destroyed it reverts back to per workspace wallpapers and toogles
    the checkbox so that the user knows what is going on.

commit 02c53a331c02300134d66da376bcb6a85d90be63
Author: Eric Koegel <eric.koegel at gmail.com>
Date:   Sun Mar 24 09:45:29 2013 +0300

    Make the image style default setting consistant

commit 9f81066800a9de6a2a20f5436e69fad2492564e2
Author: Eric Koegel <eric.koegel at gmail.com>
Date:   Mon Mar 25 19:20:41 2013 +0300

    Correctly handle workspaces being removed
    
    When workspaces are removed the xfconf bindings need to be removed
    and it also handles the single workspace number set to an invalid
    workspace.

commit 963d829f123b7cd4da36c25fa03cf5754897e195
Author: Eric Koegel <eric.koegel at gmail.com>
Date:   Sun Mar 17 14:45:27 2013 +0300

    Clip overlapping backdrops (Bug #9052)
    
    In a multi-monitor setup each successive wallpaper drawn has the
    previous area subtracted from it so that the wallpapers aren't
    drawn over each other.

commit 594ea3b79117c866b8d2358dc2b44303572e0578
Author: Eric Koegel <eric.koegel at gmail.com>
Date:   Sun Mar 17 13:36:54 2013 +0300

    Fix memory leaks

commit 95542b215411106f404e21a443ddd1e7059fff1c
Author: Eric Koegel <eric.koegel at gmail.com>
Date:   Sun Mar 17 09:37:18 2013 +0300

    Fix a warning message

commit 8e38b064c7c09c787d7af78efff4eaa59c235510
Author: Eric Koegel <eric.koegel at gmail.com>
Date:   Sat Mar 16 13:30:32 2013 +0300

    Change thumbnail and padding in the settings app
    
    Increase the thumbnail size and lower the padding between individual
    thumbnails in xfdesktop-settings.

commit f51d49ec663ae59c3c5c357eedd9c378a1fdfd13
Author: Eric Koegel <eric.koegel at gmail.com>
Date:   Sun Mar 10 11:31:45 2013 +0300

    Apply wallpaper to all workspaces option

commit c4a10cc1524490d35a6afd7aa67cdd57c59729b8
Author: Eric Koegel <eric.koegel at gmail.com>
Date:   Mon Mar 4 15:44:27 2013 +0300

    Add an iconview tooltip
    
    Add a tooltip letting the user know that the image style is set to
    none and therefore they can't select a wallpaper in the iconview.

commit d51fb8ba1ca31f1f66f2855c4e514b80b88b15de
Author: Eric Koegel <eric.koegel at gmail.com>
Date:   Sun Mar 3 16:53:06 2013 +0300

    Fix warnings and add workspace-changed signal
    
    Removed the code attempting to bind to the brightness setting since
    that functionality was removed. In xfdesktop-settings connect to the
    workspace-changed signal to properly update the image_iconview.

commit 59921a68c40f8115460553ae69bde5bda3bc7d76
Author: Eric Koegel <eric.koegel at gmail.com>
Date:   Mon Feb 25 11:49:16 2013 +0300

    Thumbnail service support to xfdesktop-settings (Bug #6536)

commit 3cec6972530e4e4af47dbb84358fa8fedcc00f82
Author: Eric Koegel <eric.koegel at gmail.com>
Date:   Tue Feb 26 10:50:20 2013 +0300

    Fixes for multi-monitor per-workspace wallpapers
    
    This fixes several issues with the per-workspace backdrop code,
    especially with multi-monitor setups. Selection mode in the settings
    app is set to browse to enforce an item is always selected. Also
    xfdesktop trys to avoid redrawing the wallpaper on a workspace
    change if the backdrops are identical. The --reload option works
    correctly again.

 common/xfdesktop-common.c                          |   61 +-
 common/xfdesktop-common.h                          |    5 +
 common/xfdesktop-thumbnailer.c                     |   49 +-
 common/xfdesktop-thumbnailer.h                     |    3 +
 settings/main.c                                    |  820 +++++++++++++++-----
 .../xfdesktop-settings-appearance-frame-ui.glade   |  488 ++++++------
 settings/xfdesktop-settings-ui.glade               |    4 +-
 src/xfce-backdrop.c                                |  210 +++--
 src/xfce-backdrop.h                                |    8 +-
 src/xfce-desktop.c                                 |  344 +++++---
 src/xfce-workspace.c                               |  180 +++--
 src/xfdesktop-file-icon-manager.c                  |  116 ---
 12 files changed, 1458 insertions(+), 830 deletions(-)

diff --git a/common/xfdesktop-common.c b/common/xfdesktop-common.c
index 344611a..755e273 100644
--- a/common/xfdesktop-common.c
+++ b/common/xfdesktop-common.c
@@ -188,13 +188,70 @@ xfdesktop_backdrop_choose_random(const gchar *filename)
     return file;
 }
 
+gchar *
+xfdesktop_get_file_mimetype(const gchar *file)
+{
+    GFile *temp_file;
+    GFileInfo *file_info;
+    gchar *mime_type = NULL;
+
+    g_return_val_if_fail(file != NULL, NULL);
+
+    temp_file = g_file_new_for_path(file);
+
+    g_return_val_if_fail(temp_file != NULL, NULL);
+
+    file_info = g_file_query_info(temp_file,
+                                  "standard::content-type",
+                                  0,
+                                  NULL,
+                                  NULL);
+
+    if(file_info != NULL) {
+        mime_type = g_strdup(g_file_info_get_content_type(file_info));
+
+        g_object_unref(file_info);
+    }
+
+    g_object_unref(temp_file);
+
+    return mime_type;
+}
+
 gboolean
 xfdesktop_image_file_is_valid(const gchar *filename)
 {
+    static GSList *pixbuf_formats = NULL;
+    GSList *l;
+    gboolean image_valid = FALSE;
+    gchar *file_mimetype;
+
     g_return_val_if_fail(filename, FALSE);
 
-    /* if gdk can get pixbuf info from the file then it's an image file */
-    return (gdk_pixbuf_get_file_info(filename, NULL, NULL) == NULL ? FALSE : TRUE);
+    if(pixbuf_formats == NULL) {
+        pixbuf_formats = gdk_pixbuf_get_formats();
+    }
+
+    file_mimetype = xfdesktop_get_file_mimetype(filename);
+
+    if(file_mimetype == NULL)
+        return FALSE;
+
+    /* Every pixbuf format has a list of mime types we can compare against */
+    for(l = pixbuf_formats; l != NULL && image_valid == FALSE; l = g_slist_next(l)) {
+        gint i;
+        gchar ** mimetypes = gdk_pixbuf_format_get_mime_types(l->data);
+
+        for(i = 0; mimetypes[i] != NULL && image_valid == FALSE; i++) {
+            if(g_strcmp0(file_mimetype, mimetypes[i]) == 0)
+                image_valid = TRUE;
+        }
+         g_strfreev(mimetypes);
+    }
+
+    g_free(file_mimetype);
+
+    return image_valid;
 }
 
 gboolean
diff --git a/common/xfdesktop-common.h b/common/xfdesktop-common.h
index 7c7570d..b34d7b5 100644
--- a/common/xfdesktop-common.h
+++ b/common/xfdesktop-common.h
@@ -49,6 +49,9 @@
 #define ARRANGE_MESSAGE    "arrange"
 #define QUIT_MESSAGE       "quit"
 
+#define SINGLE_WORKSPACE_MODE     "/backdrop/single-workspace-mode"
+#define SINGLE_WORKSPACE_NUMBER   "/backdrop/single-workspace-number"
+
 /**
  * File information namespaces queried for #GFileInfo objects.
  */
@@ -76,6 +79,8 @@ 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);
+
 gboolean xfdesktop_check_is_running(Window *xid);
 void xfdesktop_send_client_message(Window xid, const gchar *msg);
 
diff --git a/common/xfdesktop-thumbnailer.c b/common/xfdesktop-thumbnailer.c
index 8f39fe9..2c735df 100644
--- a/common/xfdesktop-thumbnailer.c
+++ b/common/xfdesktop-thumbnailer.c
@@ -41,6 +41,7 @@
 #include <libxfce4util/libxfce4util.h>
 #include "xfdesktop-thumbnailer.h"
 #include "xfdesktop-marshal.h"
+#include "xfdesktop-common.h"
 
 static void xfdesktop_thumbnailer_init(GObject *);
 static void xfdesktop_thumbnailer_class_init(GObjectClass *);
@@ -257,34 +258,14 @@ xfdesktop_thumbnailer_new(void)
     return thumbnailer_object;
 }
 
-static gchar *
-xfdesktop_get_file_mimetype(gchar *file)
+gboolean xfdesktop_thumbnailer_service_available(XfdesktopThumbnailer *thumbnailer)
 {
-    GFile *temp_file;
-    GFileInfo *file_info;
-    gchar *mime_type = NULL;
-
-    g_return_val_if_fail(file != NULL, NULL);
-
-    temp_file = g_file_new_for_path(file);
-
-    g_return_val_if_fail(temp_file != NULL, NULL);
-
-    file_info = g_file_query_info(temp_file,
-                                  "standard::content-type",
-                                  0,
-                                  NULL,
-                                  NULL);
-
-    if(file_info != NULL) {
-        mime_type = g_strdup(g_file_info_get_content_type(file_info));
+    g_return_val_if_fail(XFDESKTOP_IS_THUMBNAILER(thumbnailer), FALSE);
 
-        g_object_unref(file_info);
-    }
+    if(thumbnailer->priv->proxy == NULL)
+        return FALSE;
 
-    g_object_unref(temp_file);
-    
-    return mime_type;
+    return TRUE;
 }
 
 gboolean
@@ -370,6 +351,12 @@ xfdesktop_thumbnailer_queue_thumbnail(XfdesktopThumbnailer *thumbnailer,
     return TRUE;
 }
 
+static void
+xfdesktop_thumbnailer_dequeue_foreach(gpointer data, gpointer user_data)
+{
+    xfdesktop_thumbnailer_dequeue_thumbnail(user_data, data);
+}
+
 /**
  * xfdesktop_thumbnailer_dequeue_thumbnail:
  * 
@@ -402,9 +389,8 @@ xfdesktop_thumbnailer_dequeue_thumbnail(XfdesktopThumbnailer *thumbnailer,
     }
 
     if(g_slist_find(thumbnailer->priv->queue, file) != NULL) {
-            thumbnailer->priv->queue = g_slist_remove_all(
-                                                    thumbnailer->priv->queue,
-                                                    file);
+        thumbnailer->priv->queue = g_slist_remove_all(thumbnailer->priv->queue,
+                                                      file);
     }
 
     thumbnailer->priv->request_timer_id = g_timeout_add_full(
@@ -415,6 +401,13 @@ xfdesktop_thumbnailer_dequeue_thumbnail(XfdesktopThumbnailer *thumbnailer,
                         NULL);
 }
 
+void xfdesktop_thumbnailer_dequeue_all_thumbnails(XfdesktopThumbnailer *thumbnailer)
+{
+    g_return_if_fail(XFDESKTOP_IS_THUMBNAILER(thumbnailer));
+
+    g_slist_foreach(thumbnailer->priv->queue, (GFunc)xfdesktop_thumbnailer_dequeue_foreach, thumbnailer);
+}
+
 static gboolean
 xfdesktop_thumbnailer_queue_request_timer(XfdesktopThumbnailer *thumbnailer)
 {
diff --git a/common/xfdesktop-thumbnailer.h b/common/xfdesktop-thumbnailer.h
index 842f155..c7ea4c5 100644
--- a/common/xfdesktop-thumbnailer.h
+++ b/common/xfdesktop-thumbnailer.h
@@ -60,6 +60,8 @@ XfdesktopThumbnailer * xfdesktop_thumbnailer_new(void);
 
 GType xfdesktop_thumbnailer_get_type(void);
 
+gboolean xfdesktop_thumbnailer_service_available(XfdesktopThumbnailer *thumbnailer);
+
 gboolean xfdesktop_thumbnailer_is_supported(XfdesktopThumbnailer *thumbnailer,
                                             gchar *file);
 
@@ -67,6 +69,7 @@ gboolean xfdesktop_thumbnailer_queue_thumbnail(XfdesktopThumbnailer *thumbnailer
                                                gchar *file);
 void xfdesktop_thumbnailer_dequeue_thumbnail(XfdesktopThumbnailer *thumbnailer,
                                              gchar *file);
+void xfdesktop_thumbnailer_dequeue_all_thumbnails(XfdesktopThumbnailer *thumbnailer);
 
 void xfdesktop_thumbnailer_delete_thumbnail(XfdesktopThumbnailer *thumbnailer,
                                             gchar *src_file);
diff --git a/settings/main.c b/settings/main.c
index 441bcdc..675809c 100644
--- a/settings/main.c
+++ b/settings/main.c
@@ -50,12 +50,12 @@
 #include <libwnck/libwnck.h>
 
 #include "xfdesktop-common.h"
+#include "xfdesktop-thumbnailer.h"
 #include "xfdesktop-settings-ui.h"
 #include "xfdesktop-settings-appearance-frame-ui.h"
 
-#define PREVIEW_HEIGHT  48
-#define MAX_ASPECT_RATIO 3.0f
-#define PREVIEW_WIDTH 128
+#define PREVIEW_HEIGHT  96
+#define MAX_ASPECT_RATIO 1.5f
 
 #define SHOW_DESKTOP_MENU_PROP               "/desktop-menu/show"
 #define DESKTOP_MENU_SHOW_ICONS_PROP         "/desktop-menu/show-icons"
@@ -77,6 +77,15 @@
 #define DESKTOP_ICONS_SHOW_FILESYSTEM        "/desktop-icons/file-icons/show-filesystem"
 #define DESKTOP_ICONS_SHOW_REMOVABLE         "/desktop-icons/file-icons/show-removable"
 
+#define XFCE_BACKDROP_IMAGE_NONE             0
+#define XFCE_BACKDROP_IMAGE_SCALED           4
+#define XFCE_BACKDROP_IMAGE_SPANNING_SCREENS 6
+
+typedef struct
+{
+    GtkTreeModel *model;
+    GtkTreeIter *iter;
+} PreviewData;
 
 typedef struct
 {
@@ -87,9 +96,12 @@ typedef struct
     gchar *monitor_name;
     gulong image_list_loaded:1;
 
+    WnckWindow *wnck_window;
+
     GtkWidget *frame_image_list;
     GtkWidget *image_iconview;
     GtkWidget *btn_folder;
+    GtkWidget *chk_apply_to_all;
     GtkWidget *image_style_combo;
     GtkWidget *color_style_combo;
     GtkWidget *color1_btn;
@@ -103,14 +115,32 @@ typedef struct
     GtkWidget *random_backdrop_order_chkbox;
 
     GThread *preview_thread;
+    GAsyncQueue *preview_queue;
+
+    XfdesktopThumbnailer *thumbnailer;
+
+    GFile *selected_folder;
+    GCancellable *cancel_enumeration;
+    guint add_dir_idle_id;
 
 } AppearancePanel;
 
+typedef struct
+{
+    GFileEnumerator *file_enumerator;
+    GtkListStore *ls;
+    GtkTreeIter *selected_iter;
+    gchar *last_image;
+    gchar *file_path;
+    AppearancePanel *panel;
+} AddDirData;
+
 enum
 {
     COL_PIX = 0,
     COL_NAME,
     COL_FILENAME,
+    COL_THUMBNAIL,
     COL_COLLATE_KEY,
     N_COLS,
 };
@@ -124,22 +154,33 @@ enum
     N_ICON_COLS,
 };
 
+static void cb_xfdesktop_chk_apply_to_all(GtkCheckButton *button,
+                                          gpointer user_data);
+static gchar *xfdesktop_settings_generate_per_workspace_binding_string(AppearancePanel *panel,
+                                                                       const gchar* property);
+
 
-/* assumes gdk lock is held on function enter, and should be held
- * on function exit */
 static void
 xfdesktop_settings_do_single_preview(GtkTreeModel *model,
                                      GtkTreeIter *iter)
 {
-    gchar *name = NULL, *new_name = NULL, *filename = NULL;
+    gchar *filename = NULL, *thumbnail = NULL;
     GdkPixbuf *pix, *pix_scaled = NULL;
 
+    GDK_THREADS_ENTER ();
     gtk_tree_model_get(model, iter,
-                       COL_NAME, &name,
                        COL_FILENAME, &filename,
+                       COL_THUMBNAIL, &thumbnail,
                        -1);
+    GDK_THREADS_LEAVE ();
+
+    if(thumbnail == NULL) {
+        pix = gdk_pixbuf_new_from_file(filename, NULL);
+    } else {
+        pix = gdk_pixbuf_new_from_file(thumbnail, NULL);
+        g_free(thumbnail);
+    }
 
-    pix = gdk_pixbuf_new_from_file(filename, NULL);
     g_free(filename);
     if(pix) {
         gint width, height;
@@ -147,10 +188,6 @@ xfdesktop_settings_do_single_preview(GtkTreeModel *model,
 
         width = gdk_pixbuf_get_width(pix);
         height = gdk_pixbuf_get_height(pix);
-        /* no need to escape markup; it's already done for us */
-        new_name = g_strdup_printf(_("%s\n<i>Size: %dx%d</i>"),
-                                   name, width, height);
-
         aspect = (gdouble)width / height;
 
         /* Keep the aspect ratio sensible otherwise the treeview looks bad */
@@ -165,57 +202,132 @@ xfdesktop_settings_do_single_preview(GtkTreeModel *model,
 
         g_object_unref(G_OBJECT(pix));
     }
-    g_free(name);
-
-    if(new_name) {
-        gtk_list_store_set(GTK_LIST_STORE(model), iter,
-                           COL_NAME, new_name,
-                           -1);
-        g_free(new_name);
-    }
 
     if(pix_scaled) {
+        GDK_THREADS_ENTER ();
         gtk_list_store_set(GTK_LIST_STORE(model), iter,
                            COL_PIX, pix_scaled,
                            -1);
+        GDK_THREADS_LEAVE ();
         g_object_unref(G_OBJECT(pix_scaled));
     }
 }
 
+static void
+xfdesktop_settings_free_pdata(gpointer data)
+{
+    PreviewData *pdata = data;
+    g_object_unref(G_OBJECT(pdata->model));
+    gtk_tree_iter_free(pdata->iter);
+    g_free(pdata);
+}
+
 static gpointer
-xfdesktop_settings_create_all_previews(gpointer data)
+xfdesktop_settings_create_previews(gpointer data)
 {
-    GtkTreeModel *model = data;
-    GtkTreeView *tree_view;
-    GtkTreeIter iter;
+    AppearancePanel *panel = data;
 
-    GDK_THREADS_ENTER ();
+    while(panel->preview_queue != NULL) {
+        PreviewData *pdata = NULL;
 
-    if(gtk_tree_model_get_iter_first(model, &iter)) {
-        do {
-            xfdesktop_settings_do_single_preview(model, &iter);
-        } while(gtk_tree_model_iter_next(model, &iter));
+        /* Block and wait for another preview to create */
+        pdata = g_async_queue_pop(panel->preview_queue);
+
+        xfdesktop_settings_do_single_preview(pdata->model, pdata->iter);
+
+        xfdesktop_settings_free_pdata(pdata);
     }
 
-    /* if possible, scroll to the selected image */
-    tree_view = g_object_get_data(G_OBJECT(model), "xfdesktop-tree-view");
-    if(tree_view) {
-        GtkTreeSelection *selection = gtk_tree_view_get_selection(tree_view);
+    return NULL;
+}
 
-        if(gtk_tree_selection_get_mode(selection) != GTK_SELECTION_MULTIPLE
-           && gtk_tree_selection_get_selected(selection, NULL, &iter))
+static void
+xfdesktop_settings_add_file_to_queue(AppearancePanel *panel, PreviewData *pdata)
+{
+    TRACE("entering");
+
+    g_return_if_fail(panel != NULL);
+    g_return_if_fail(pdata != NULL);
+
+    /* Create the queue if it doesn't exist */
+    if(panel->preview_queue == NULL) {
+        panel->preview_queue = g_async_queue_new_full(xfdesktop_settings_free_pdata);
+    }
+
+    g_async_queue_push(panel->preview_queue, pdata);
+
+    /* Create the thread if it doesn't exist */
+    if(panel->preview_thread == NULL) {
+        panel->preview_thread = g_thread_try_new("xfdesktop_settings_create_previews",
+                                                 xfdesktop_settings_create_previews,
+                                                 panel, NULL);
+        if(panel->preview_thread == NULL)
         {
-            GtkTreePath *path = gtk_tree_model_get_path(model, &iter);
-            gtk_tree_view_scroll_to_cell(tree_view, path, NULL, TRUE, 0.0, 0.0);
+                g_critical("Unable to create thread for image previews.");
+                /* Don't block but try to remove the data from the queue
+                 * since we won't be creating previews */
+                if(g_async_queue_try_pop(panel->preview_queue))
+                    xfdesktop_settings_free_pdata(pdata);
         }
     }
-    g_object_set_data(G_OBJECT(model), "xfdesktop-tree-view", NULL);
+}
 
-    GDK_THREADS_LEAVE ();
+static void
+cb_thumbnail_ready(XfdesktopThumbnailer *thumbnailer,
+                   gchar *src_file, gchar *thumb_file,
+                   gpointer user_data)
+{
+    AppearancePanel *panel = user_data;
+    GtkTreeModel *model = gtk_icon_view_get_model(GTK_ICON_VIEW(panel->image_iconview));
+    GtkTreeIter iter;
+    PreviewData *pdata = NULL;
 
-    g_object_unref(G_OBJECT(model));
+    if(gtk_tree_model_get_iter_first(model, &iter)) {
+        do {
+            gchar *filename = NULL;
+            gtk_tree_model_get(model, &iter, COL_FILENAME, &filename, -1);
 
-    return NULL;
+            /* We're looking for the src_file */
+            if(g_strcmp0(filename, src_file) == 0) {
+                /* Add the thumb_file to it */
+                gtk_list_store_set(GTK_LIST_STORE(model), &iter,
+                                   COL_THUMBNAIL, thumb_file, -1);
+
+                pdata = g_new0(PreviewData, 1);
+                pdata->model = g_object_ref(G_OBJECT(model));
+                pdata->iter = gtk_tree_iter_copy(&iter);
+
+                /* Create the preview image */
+                xfdesktop_settings_add_file_to_queue(panel, pdata);
+
+                g_free(filename);
+                return;
+            }
+
+            g_free(filename);
+        } while(gtk_tree_model_iter_next(model, &iter));
+    }
+}
+
+static void
+xfdesktop_settings_queue_preview(GtkTreeModel *model,
+                                 GtkTreeIter *iter,
+                                 AppearancePanel *panel)
+{
+    gchar *filename;
+
+    gtk_tree_model_get(model, iter, COL_FILENAME, &filename, -1);
+
+    /* Attempt to use the thumbnailer if possible */
+    if(!xfdesktop_thumbnailer_queue_thumbnail(panel->thumbnailer, filename)) {
+        /* Thumbnailing not possible, add it to the queue to be loaded manually */
+        PreviewData *pdata;
+        pdata = g_new0(PreviewData, 1);
+        pdata->model = g_object_ref(G_OBJECT(model));
+        pdata->iter = gtk_tree_iter_copy(iter);
+
+        xfdesktop_settings_add_file_to_queue(panel, pdata);
+    }
 }
 
 static void
@@ -332,7 +444,7 @@ image_list_compare(GtkTreeModel *model,
     gchar *key_b = NULL;
     gint ret;
 
-    gtk_tree_model_get(model, b, COL_NAME, &key_b, -1);
+    gtk_tree_model_get(model, b, COL_COLLATE_KEY, &key_b, -1);
 
     ret = g_strcmp0(a, key_b);
 
@@ -343,48 +455,60 @@ image_list_compare(GtkTreeModel *model,
 
 static GtkTreeIter *
 xfdesktop_settings_image_iconview_add(GtkTreeModel *model,
-                                      const char *path)
+                                      const char *path,
+                                      GFileInfo *info,
+                                      AppearancePanel *panel)
 {
     gboolean added = FALSE, found = FALSE, valid = FALSE;
     GtkTreeIter iter, search_iter;
-    gchar *name = NULL, *name_utf8 = NULL, *name_markup = NULL;
-    gchar *lower = NULL;
+    gchar *name = NULL, *name_utf8 = NULL, *name_markup = NULL, *size_string = NULL;
+    gchar *collate_key = NULL;
+    gint position = 0;
+    const gchar *content_type = g_file_info_get_content_type(info);
+    goffset file_size = g_file_info_get_size(info);
 
     if(!xfdesktop_image_file_is_valid(path))
         return NULL;
 
     name = g_path_get_basename(path);
     if(name) {
-        name_utf8 = g_filename_to_utf8(name, strlen(name),
+        guint name_length = strlen(name);
+        name_utf8 = g_filename_to_utf8(name, name_length,
                                        NULL, NULL, NULL);
         if(name_utf8) {
-            name_markup = g_markup_printf_escaped("<b>%s</b>",
-                                                  name_utf8);
+#if GLIB_CHECK_VERSION (2, 30, 0)
+            size_string = g_format_size(file_size);
+#else
+            size_string = g_format_size_for_display(file_size);
+#endif
 
-            lower = g_utf8_strdown(name_utf8, -1);
+            /* Display the file name, file type, and file size in the tooltip. */
+            name_markup = g_markup_printf_escaped(_("<b>%s</b>\nType: %s\nSize: %s"),
+                                                  name_utf8, content_type, size_string);
+
+            /* create a case sensitive collation key for sorting filenames like
+             * Thunar does */
+            collate_key = g_utf8_collate_key_for_filename(name, name_length);
 
             /* Insert sorted */
             valid = gtk_tree_model_get_iter_first(model, &search_iter);
             while(valid && !found) {
-                if(image_list_compare(model, name_markup, &search_iter) <= 0) {
+                if(image_list_compare(model, collate_key, &search_iter) <= 0) {
                     found = TRUE;
                 } else {
                     valid = gtk_tree_model_iter_next(model, &search_iter);
+                    position++;
                 }
             }
 
-            if(!found) {
-                gtk_list_store_append(GTK_LIST_STORE(model), &iter);
-            } else {
-                gtk_list_store_insert_before(GTK_LIST_STORE(model), &iter, &search_iter);
-            }
-
-
-            gtk_list_store_set(GTK_LIST_STORE(model), &iter,
-                               COL_NAME, name_markup,
-                               COL_FILENAME, path,
-                               COL_COLLATE_KEY, lower,
-                               -1);
+            gtk_list_store_insert_with_values(GTK_LIST_STORE(model),
+                                              &iter,
+                                              position,
+                                              COL_NAME, name_markup,
+                                              COL_FILENAME, path,
+                                              COL_COLLATE_KEY, collate_key,
+                                              -1);
+            xfdesktop_settings_queue_preview(model, &iter, panel);
 
             added = TRUE;
         }
@@ -393,7 +517,8 @@ xfdesktop_settings_image_iconview_add(GtkTreeModel *model,
     g_free(name);
     g_free(name_utf8);
     g_free(name_markup);
-    g_free(lower);
+    g_free(size_string);
+    g_free(collate_key);
 
     if(added)
         return gtk_tree_iter_copy(&iter);
@@ -401,40 +526,120 @@ xfdesktop_settings_image_iconview_add(GtkTreeModel *model,
         return NULL;
 }
 
-static GtkTreeIter *
-xfdesktop_image_list_add_dir(GtkListStore *ls,
-                             const char *path,
-                             const char *cur_image_file)
+static void
+cb_destroy_add_dir_enumeration(gpointer user_data)
 {
-    GDir *dir;
-    gboolean needs_slash = TRUE;
-    const gchar *file;
-    GtkTreeIter *iter, *iter_ret = NULL;
-    gchar buf[PATH_MAX];
-
-    dir = g_dir_open(path, 0, 0);
-    if(!dir)
-        return NULL;
+    AddDirData *dir_data = user_data;
+    AppearancePanel *panel = dir_data->panel;
+
+    TRACE("entering");
+
+    g_free(dir_data->file_path);
+    g_free(dir_data->last_image);
+
+    if(G_IS_FILE_ENUMERATOR(dir_data->file_enumerator))
+        g_object_unref(dir_data->file_enumerator);
 
-    if(path[strlen(path)-1] == '/')
-        needs_slash = FALSE;
+    g_free(dir_data);
 
-    while((file = g_dir_read_name(dir))) {
-        g_snprintf(buf, sizeof(buf), needs_slash ? "%s/%s" : "%s%s",
-                   path, file);
+    if(panel->cancel_enumeration) {
+        g_object_unref(panel->cancel_enumeration);
+        panel->cancel_enumeration = NULL;
+    }
+}
+
+static gboolean
+xfdesktop_image_list_add_item(gpointer user_data)
+{
+    AddDirData *dir_data = user_data;
+    AppearancePanel *panel = dir_data->panel;
+    GFileInfo *info;
+    GtkTreeIter *iter;
 
-        iter = xfdesktop_settings_image_iconview_add(GTK_TREE_MODEL(ls), buf);
+    /* If the enumeration gets canceled/destroyed return and
+     * cb_destroy_add_dir_enumeration will get called to clean up */
+    if(!G_IS_FILE_ENUMERATOR(dir_data->file_enumerator))
+        return FALSE;
+
+    /* Add one item to the icon view at a time so we don't block the UI */
+    if((info = g_file_enumerator_next_file(dir_data->file_enumerator, NULL, NULL))) {
+        const gchar *file_name = g_file_info_get_name(info);
+        gchar *buf = g_strconcat(dir_data->file_path, "/", file_name, NULL);
+
+        iter = xfdesktop_settings_image_iconview_add(GTK_TREE_MODEL(dir_data->ls), buf, info, panel);
         if(iter) {
-            if(cur_image_file && !iter_ret && !strcmp(buf, cur_image_file))
-                iter_ret = iter;
-            else
+            if(!dir_data->selected_iter &&
+               !strcmp(buf, dir_data->last_image))
+            {
+                dir_data->selected_iter = iter;
+            } else {
                 gtk_tree_iter_free(iter);
+            }
         }
+
+        g_free(buf);
+        g_object_unref(info);
+
+        /* continue on the next idle callback so the user's events get priority */
+        return TRUE;
     }
 
-    g_dir_close(dir);
+    /* If we get here we're done enumerating files in the directory */
+
+    gtk_icon_view_set_model(GTK_ICON_VIEW(panel->image_iconview),
+                            GTK_TREE_MODEL(dir_data->ls));
+
+    /* last_image is in the directory added then it should be selected */
+    if(dir_data->selected_iter) {
+        GtkTreePath *path;
+        path = gtk_tree_model_get_path(GTK_TREE_MODEL(dir_data->ls), dir_data->selected_iter);
+        if(path) {
+            gtk_icon_view_select_path(GTK_ICON_VIEW(panel->image_iconview), path);
+            gtk_tree_iter_free(dir_data->selected_iter);
+            gtk_tree_path_free(path);
+        }
+     }
+
+    /* cb_destroy_add_dir_enumeration will get called to clean up */
+    return FALSE;
+}
+
+static void
+xfdesktop_image_list_add_dir(GObject *source_object,
+                             GAsyncResult *res,
+                             gpointer user_data)
+{
+    AppearancePanel *panel = user_data;
+    gchar *property;
+    AddDirData *dir_data = g_new0(AddDirData, 1);
+
+    TRACE("entering");
+
+    dir_data->panel = panel;
+
+    dir_data->ls = gtk_list_store_new(N_COLS, GDK_TYPE_PIXBUF, G_TYPE_STRING,
+                                      G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
+
+    /* Get the last image/current image displayed so we can select it in the
+     * icon view */
+    property = xfdesktop_settings_generate_per_workspace_binding_string(panel, "last-image");
+
+    dir_data->last_image = xfconf_channel_get_string(panel->channel, property, DEFAULT_BACKDROP);
+
+    dir_data->file_path = g_file_get_path(panel->selected_folder);
+
+    dir_data->file_enumerator = g_file_enumerate_children_finish(panel->selected_folder,
+                                                                 res,
+                                                                 NULL);
+
+    /* Individual items are added in an idle callback so everything is more
+     * responsive */
+    panel->add_dir_idle_id = g_idle_add_full(G_PRIORITY_DEFAULT_IDLE,
+                                             xfdesktop_image_list_add_item,
+                                             dir_data,
+                                             cb_destroy_add_dir_enumeration);
 
-    return iter_ret;
+    g_free(property);
 }
 
 static void
@@ -447,16 +652,44 @@ xfdesktop_settings_update_iconview_frame_name(AppearancePanel *panel,
     if(panel->monitor < 0 && panel->workspace < 0)
         return;
 
+    if(wnck_workspace == NULL) {
+        WnckScreen *wnck_screen = wnck_window_get_screen(panel->wnck_window);
+        wnck_workspace = wnck_screen_get_active_workspace(wnck_screen);
+    }
+
     workspace_name = g_strdup(wnck_workspace_get_name(wnck_workspace));
 
-    if(panel->monitor_name) {
-        g_snprintf(buf, sizeof(buf),
-                   _("Wallpaper for %s on Monitor %d (%s)"),
-                   workspace_name, panel->monitor, panel->monitor_name);
-    } else
-        g_snprintf(buf, sizeof(buf),
-                   _("Wallpaper for %s on Monitor %d"),
-                   workspace_name, panel->monitor);
+    if(gdk_screen_get_n_monitors(gtk_widget_get_screen(panel->chk_apply_to_all)) > 1) {
+        if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(panel->chk_apply_to_all))) {
+            /* Multi-monitor single workspace */
+            if(panel->monitor_name) {
+                g_snprintf(buf, sizeof(buf),
+                           _("Wallpaper for Monitor %d (%s)"),
+                           panel->monitor, panel->monitor_name);
+            } else {
+                g_snprintf(buf, sizeof(buf), _("Wallpaper for Monitor %d"), panel->monitor);
+            }
+        } else {
+            /* Multi-monitor per workspace wallpaper */
+            if(panel->monitor_name) {
+                g_snprintf(buf, sizeof(buf),
+                           _("Wallpaper for %s on Monitor %d (%s)"),
+                           workspace_name, panel->monitor, panel->monitor_name);
+            } else {
+                g_snprintf(buf, sizeof(buf),
+                           _("Wallpaper for %s on Monitor %d"),
+                           workspace_name, panel->monitor);
+            }
+        }
+    } else {
+        if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(panel->chk_apply_to_all))) {
+            /* Single monitor and single workspace */
+            g_snprintf(buf, sizeof(buf), _("Wallpaper for my desktop"));
+        } else {
+            /* Single monitor and per workspace wallpaper */
+            g_snprintf(buf, sizeof(buf), _("Wallpaper for %s"), workspace_name);
+        }
+    }
 
     gtk_frame_set_label(GTK_FRAME(panel->frame_image_list), buf);
 
@@ -480,6 +713,8 @@ xfdesktop_settings_generate_per_workspace_binding_string(AppearancePanel *panel,
                               property);
     }
 
+    DBG("name %s", buf);
+
     return buf;
 }
 
@@ -528,11 +763,52 @@ cb_image_selection_changed(GtkIconView *icon_view,
         xfconf_channel_set_string(panel->channel, buf, filename);
     }
 
+    g_list_foreach (selected_items, (GFunc)gtk_tree_path_free, NULL);
     g_list_free(selected_items);
     g_free(current_filename);
     g_free(buf);
 }
 
+static gint
+xfdesktop_settings_get_active_workspace(AppearancePanel *panel,
+                                        WnckWindow *wnck_window)
+{
+    WnckWorkspace *wnck_workspace;
+    gboolean single_workspace;
+    gint workspace_num, single_workspace_num;
+    WnckScreen *wnck_screen = wnck_window_get_screen(wnck_window);
+
+    wnck_workspace = wnck_window_get_workspace(wnck_window);
+
+    if(wnck_workspace != NULL) {
+        workspace_num = wnck_workspace_get_number(wnck_workspace);
+    } else {
+        workspace_num = wnck_workspace_get_number(wnck_screen_get_active_workspace(wnck_screen));
+    }
+
+
+    single_workspace = xfconf_channel_get_bool(panel->channel,
+                                               SINGLE_WORKSPACE_MODE,
+                                               TRUE);
+
+    /* If we're in single_workspace mode we need to return the workspace that
+     * it was set to, if that workspace exists, otherwise return the current
+     * workspace and turn off the single workspace mode */
+    if(single_workspace) {
+        single_workspace_num = xfconf_channel_get_int(panel->channel,
+                                                      SINGLE_WORKSPACE_NUMBER,
+                                                      0);
+        if(single_workspace_num < wnck_screen_get_workspace_count(wnck_screen)) {
+            return single_workspace_num;
+        } else {
+            gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(panel->chk_apply_to_all),
+                                         FALSE);
+        }
+    }
+
+    return workspace_num;
+}
+
 static void
 cb_xfdesktop_chk_custom_font_size_toggled(GtkCheckButton *button,
                                           gpointer user_data)
@@ -602,61 +878,125 @@ cb_xfdesktop_spin_icon_size_changed(GtkSpinButton *button,
 }
 
 static void
+xfdesktop_settings_stop_image_loading(AppearancePanel *panel)
+{
+    /* stop any thumbnailing in progress */
+    xfdesktop_thumbnailer_dequeue_all_thumbnails(panel->thumbnailer);
+
+    /* Remove the previews in the message queue */
+    if(panel->preview_queue != NULL) {
+        while(g_async_queue_length(panel->preview_queue) > 0) {
+            gpointer data = g_async_queue_try_pop(panel->preview_queue);
+            if(data)
+                xfdesktop_settings_free_pdata(data);
+        }
+    }
+
+    /* Cancel any file enumeration that's running */
+    if(panel->cancel_enumeration != NULL) {
+        g_cancellable_cancel(panel->cancel_enumeration);
+        g_object_unref(panel->cancel_enumeration);
+        panel->cancel_enumeration = NULL;
+    }
+
+    /* Cancel the file enumeration for populating the icon view */
+    if(panel->add_dir_idle_id != 0) {
+        g_source_remove(panel->add_dir_idle_id);
+        panel->add_dir_idle_id = 0;
+    }
+}
+
+static void
+cb_xfdesktop_bnt_exit_clicked(GtkButton *button, gpointer user_data)
+{
+    AppearancePanel *panel = user_data;
+
+    xfdesktop_settings_stop_image_loading(panel);
+}
+
+static void
 cb_folder_selection_changed(GtkWidget *button,
                             gpointer user_data)
 {
     AppearancePanel *panel = user_data;
     gchar *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(button));
-    GtkListStore *ls;
-    GtkTreeIter *iter;
-    GtkTreePath *path;
-    gchar *last_image, *property;
+    gchar *previous_filename = NULL;
 
     TRACE("entering");
 
-    ls = gtk_list_store_new(N_COLS, GDK_TYPE_PIXBUF, G_TYPE_STRING,
-                            G_TYPE_STRING, G_TYPE_STRING);
+    if(panel->selected_folder != NULL)
+        previous_filename = g_file_get_path(panel->selected_folder);
 
-    property = xfdesktop_settings_generate_per_workspace_binding_string(panel, "last-image");
+    /* Check to see if the folder actually did change */
+    if(g_strcmp0(filename, previous_filename) == 0) {
+        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;
+    }
 
-    last_image = xfconf_channel_get_string(panel->channel, property, NULL);
+    TRACE("folder changed to: %s", filename);
 
-    if(last_image == NULL)
-        last_image = DEFAULT_BACKDROP;
+    if(panel->selected_folder != NULL)
+        g_object_unref(panel->selected_folder);
 
-    iter = xfdesktop_image_list_add_dir(ls, filename, last_image);
+    panel->selected_folder = g_file_new_for_path(filename);
 
-    gtk_icon_view_set_model(GTK_ICON_VIEW(panel->image_iconview),
-                            GTK_TREE_MODEL(ls));
- 
-    /* last_image is in the directory added then it should be selected */
-    if(iter) {
-        path = gtk_tree_model_get_path(GTK_TREE_MODEL(ls), iter);
-        if(path) {
-            gtk_icon_view_select_path(GTK_ICON_VIEW(panel->image_iconview), path);
-            gtk_tree_iter_free(iter);
-        }
-     }
+    /* Stop any previous loading since something changed */
+    xfdesktop_settings_stop_image_loading(panel);
 
-    /* remove any preview threads that may still be running since we've probably
-     * changed to a new monitor/workspace */
-    if(panel->preview_thread != NULL) {
-        g_thread_unref(panel->preview_thread);
-        panel->preview_thread = NULL;
-    }
+    panel->cancel_enumeration = g_cancellable_new();
 
-    /* generate previews of each image -- the new thread will own
-     * the reference on the list store, so let's not unref it here */
-    panel->preview_thread = g_thread_try_new("xfdesktop_settings_create_all_previews",
-                                             xfdesktop_settings_create_all_previews,
-                                             ls, NULL);
+    g_file_enumerate_children_async(panel->selected_folder,
+                                    XFDESKTOP_FILE_INFO_NAMESPACE,
+                                    G_FILE_QUERY_INFO_NONE,
+                                    G_PRIORITY_DEFAULT,
+                                    panel->cancel_enumeration,
+                                    xfdesktop_image_list_add_dir,
+                                    panel);
 
-    if(panel->preview_thread == NULL) {
-        g_critical("Failed to spawn thread; backdrop previews will be unavailable.");
-        g_object_unref(G_OBJECT(ls));
-    }
+    g_free(filename);
+    g_free(previous_filename);
+}
 
-    g_free(property);
+static void
+cb_xfdesktop_combo_image_style_changed(GtkComboBox *combo,
+                                       gpointer user_data)
+{
+    AppearancePanel *panel = user_data;
+
+    TRACE("entering");
+
+    if(gtk_combo_box_get_active(combo) == XFCE_BACKDROP_IMAGE_NONE) {
+        /* No wallpaper so set the iconview to insensitive so the user doesn't
+         * pick wallpapers that have no effect. Stop popping up tooltips for
+         * the now insensitive iconview and provide a tooltip explaining why
+         * the iconview is insensitive. */
+        gtk_widget_set_sensitive(panel->image_iconview, FALSE);
+        g_object_set(G_OBJECT(panel->image_iconview),
+                     "tooltip-column", -1,
+                     NULL);
+        gtk_widget_set_tooltip_text(panel->image_iconview,
+                                    _("Image selection is unavailable while the image style is set to None."));
+    } else {
+        gint tooltip_column;
+
+        /* We are expected to provide a wallpaper so make the iconview active.
+         * Additionally, if we were insensitive then we need to remove the
+         * global iconview tooltip and enable the individual tooltips again. */
+        gtk_widget_set_sensitive(panel->image_iconview, TRUE);
+        g_object_get(G_OBJECT(panel->image_iconview),
+                     "tooltip-column", &tooltip_column,
+                     NULL);
+        if(tooltip_column == -1) {
+            gtk_widget_set_tooltip_text(panel->image_iconview, NULL);
+            g_object_set(G_OBJECT(panel->image_iconview),
+                         "tooltip-column", COL_NAME,
+                         NULL);
+        }
+    }
 }
 
 static void
@@ -688,22 +1028,22 @@ cb_xfdesktop_combo_color_changed(GtkComboBox *combo,
 static void
 xfdesktop_settings_update_iconview_folder(AppearancePanel *panel)
 {
-    gchar *current_folder, *prop_last;
+    gchar *current_folder, *prop_last, *dirname;
 
     TRACE("entering");
 
     prop_last = xfdesktop_settings_generate_per_workspace_binding_string(panel, "last-image");
+    current_folder = xfconf_channel_get_string(panel->channel, prop_last, DEFAULT_BACKDROP);
+    dirname = g_path_get_dirname(current_folder);
 
-    current_folder = xfconf_channel_get_string(panel->channel, prop_last, NULL);
-
-    if(current_folder == NULL)
-        current_folder = g_strdup(DEFAULT_BACKDROP);
+    gtk_file_chooser_set_current_folder((GtkFileChooser*)panel->btn_folder, dirname);
 
-    gtk_file_chooser_set_current_folder((GtkFileChooser*)panel->btn_folder,
-                                  g_path_get_dirname(current_folder));
+    /* Workaround for a bug in GTK */
+    cb_folder_selection_changed(panel->btn_folder, panel);
 
     g_free(current_folder);
     g_free(prop_last);
+    g_free(dirname);
 }
 
 /* This function is to add or remove all the bindings for the background
@@ -723,6 +1063,8 @@ xfdesktop_settings_background_tab_change_bindings(AppearancePanel *panel,
     } else {
         xfconf_g_property_bind(channel, buf, G_TYPE_INT,
                                G_OBJECT(panel->image_style_combo), "active");
+        /* determine if the iconview is sensitive */
+        cb_xfdesktop_combo_image_style_changed(GTK_COMBO_BOX(panel->image_style_combo), panel);
     }
     g_free(buf);
 
@@ -734,12 +1076,15 @@ xfdesktop_settings_background_tab_change_bindings(AppearancePanel *panel,
     } else {
         xfconf_g_property_bind(channel, buf, G_TYPE_INT,
                                G_OBJECT(panel->color_style_combo), "active");
+        /* update the color button sensitivity */
+        cb_xfdesktop_combo_color_changed(GTK_COMBO_BOX(panel->color_style_combo), panel);
     }
     g_free(buf);
 
     buf = xfdesktop_settings_generate_per_workspace_binding_string(panel, "color1");
     if(remove_binding) {
         xfconf_g_property_unbind(panel->color1_btn_id);
+    } else {
         panel->color1_btn_id = xfconf_g_property_bind_gdkcolor(channel, buf,
                                                                G_OBJECT(panel->color1_btn),
                                                                "color");
@@ -756,9 +1101,6 @@ xfdesktop_settings_background_tab_change_bindings(AppearancePanel *panel,
     }
     g_free(buf);
 
-    cb_xfdesktop_combo_color_changed(GTK_COMBO_BOX(panel->color_style_combo),
-                                     panel);
-
     /* Cycle timer options */
     buf = xfdesktop_settings_generate_per_workspace_binding_string(panel, "backdrop-cycle-enable");
     if(remove_binding) {
@@ -792,8 +1134,6 @@ xfdesktop_settings_background_tab_change_bindings(AppearancePanel *panel,
     }
     g_free(buf);
 
-    cb_xfdesktop_chk_cycle_backdrop_toggled(GTK_CHECK_BUTTON(panel->backdrop_cycle_chkbox),
-                                            panel);
 }
 
 static void
@@ -810,21 +1150,24 @@ cb_update_background_tab(WnckWindow *wnck_window,
 {
     AppearancePanel *panel = user_data;
     gint screen_num, monitor_num, workspace_num;
+    gchar *monitor_name = NULL;
     WnckWorkspace *wnck_workspace = NULL;
     GdkScreen *screen;
 
     screen = gtk_widget_get_screen(panel->image_iconview);
     wnck_workspace = wnck_window_get_workspace(wnck_window);
 
-    workspace_num = wnck_workspace_get_number(wnck_workspace);
+    workspace_num = xfdesktop_settings_get_active_workspace(panel, wnck_window);
     screen_num = gdk_screen_get_number(screen);
     monitor_num = gdk_screen_get_monitor_at_window(screen,
                                                    gtk_widget_get_window(panel->image_iconview));
+    monitor_name = gdk_screen_get_monitor_plug_name(screen, monitor_num);
 
     /* Check to see if something changed */
     if(panel->workspace == workspace_num &&
        panel->screen == screen_num &&
-       panel->monitor == monitor_num) {
+       panel->monitor_name != NULL &&
+       g_strcmp0(panel->monitor_name, monitor_name) == 0) {
            return;
     }
 
@@ -844,23 +1187,75 @@ cb_update_background_tab(WnckWindow *wnck_window,
     panel->monitor = monitor_num;
     panel->monitor_name = gdk_screen_get_monitor_plug_name(screen, panel->monitor);
 
+    /* The first monitor has the option of doing the "spanning screens" style,
+     * but only if there's multiple monitors attached. Remove it in all other cases.
+     *
+     * Remove the spanning screens option before we potentially add it again
+     */
+    gtk_combo_box_text_remove(GTK_COMBO_BOX_TEXT(panel->image_style_combo),
+                              XFCE_BACKDROP_IMAGE_SPANNING_SCREENS);
+    if(panel->monitor == 0 && gdk_screen_get_n_monitors(screen) > 1) {
+        gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(panel->image_style_combo),
+                                       _("Spanning screens"));
+    }
+
     /* connect the new bindings */
     xfdesktop_settings_background_tab_change_bindings(panel,
                                                       FALSE);
 
     xfdesktop_settings_update_iconview_frame_name(panel, wnck_workspace);
     xfdesktop_settings_update_iconview_folder(panel);
+}
 
-    /* The first monitor has the option of doing the "spanning screens" style,
-     * but only if there's multiple monitors attached. Make it invisible
-     * in all other cases.
-     * Remove the spanning screens option before we potentially add it again
-     */
-    gtk_combo_box_text_remove(GTK_COMBO_BOX_TEXT(panel->image_style_combo), 6);
-    if(panel->monitor == 0 && gdk_screen_get_n_monitors(screen) > 1) {
-        gtk_combo_box_text_insert_text(GTK_COMBO_BOX_TEXT(panel->image_style_combo),
-                                       6, _("Spanning screens"));
+static void
+cb_workspace_changed(WnckScreen *screen,
+                     WnckWorkspace *workspace,
+                     gpointer user_data)
+{
+    AppearancePanel *panel = user_data;
+
+    /* Update background because the single workspace mode may have
+     * changed due to the addition/removal of a workspace */
+    cb_update_background_tab(panel->wnck_window, user_data);
+}
+
+static void
+cb_monitor_changed(GdkScreen *gscreen,
+                   gpointer user_data)
+{
+    AppearancePanel *panel = user_data;
+
+    /* Update background because the monitor we're on may have changed */
+    cb_update_background_tab(panel->wnck_window, user_data);
+
+    /* Update the frame name because we may change from/to a single monitor */
+    xfdesktop_settings_update_iconview_frame_name(panel, wnck_window_get_workspace(panel->wnck_window));
+}
+
+static void
+cb_xfdesktop_chk_apply_to_all(GtkCheckButton *button,
+                              gpointer user_data)
+{
+    AppearancePanel *panel = user_data;
+    gboolean active;
+    active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button));
+
+    TRACE("entering");
+
+    xfconf_channel_set_bool(panel->channel,
+                            SINGLE_WORKSPACE_MODE,
+                            active);
+
+    if(active) {
+        xfconf_channel_set_int(panel->channel,
+                               SINGLE_WORKSPACE_NUMBER,
+                               panel->workspace);
+    } else {
+        cb_update_background_tab(panel->wnck_window, panel);
     }
+
+    /* update the frame name to since we changed to/from single workspace mode */
+    xfdesktop_settings_update_iconview_frame_name(panel, wnck_window_get_workspace(panel->wnck_window));
 }
 
 static void
@@ -870,36 +1265,52 @@ xfdesktop_settings_setup_image_iconview(AppearancePanel *panel)
 
     TRACE("entering");
 
+    panel->thumbnailer = xfdesktop_thumbnailer_new();
+
     g_object_set(G_OBJECT(iconview),
                 "pixbuf-column", COL_PIX,
-                "item-width", PREVIEW_WIDTH,
                 "tooltip-column", COL_NAME,
+                "selection-mode", GTK_SELECTION_BROWSE,
+                "column-spacing", 1,
+                "row-spacing", 1,
+                "item-padding", 10,
+                "margin", 2,
                 NULL);
 
     g_signal_connect(G_OBJECT(iconview), "selection-changed",
                      G_CALLBACK(cb_image_selection_changed), panel);
+
+    g_signal_connect(panel->thumbnailer, "thumbnail-ready",
+                     G_CALLBACK(cb_thumbnail_ready), panel);
 }
 
 static void
 xfdesktop_settings_dialog_setup_tabs(GtkBuilder *main_gxml,
                                      XfconfChannel *channel,
-                                     GdkScreen *screen)
+                                     GdkScreen *screen,
+                                     gulong window_xid)
 {
     GtkWidget *appearance_container, *chk_custom_font_size,
               *spin_font_size, *w, *box, *spin_icon_size,
-              *chk_show_thumbnails, *chk_single_click, *appearance_settings;
+              *chk_show_thumbnails, *chk_single_click, *appearance_settings,
+              *bnt_exit;
     GtkBuilder *appearance_gxml;
     AppearancePanel *panel = g_new0(AppearancePanel, 1);
     GError *error = NULL;
     GtkFileFilter *filter;
     WnckScreen *wnck_screen;
-    WnckWindow *wnck_window = NULL;
 
     TRACE("entering");
 
     appearance_container = GTK_WIDGET(gtk_builder_get_object(main_gxml,
                                                              "notebook_screens"));
 
+    bnt_exit = GTK_WIDGET(gtk_builder_get_object(main_gxml, "bnt_exit"));
+
+    g_signal_connect(G_OBJECT(bnt_exit), "clicked",
+                     G_CALLBACK(cb_xfdesktop_bnt_exit_clicked),
+                     panel);
+
     /* Icons tab */
     /* icon size */
     spin_icon_size = GTK_WIDGET(gtk_builder_get_object(main_gxml, "spin_icon_size"));
@@ -944,10 +1355,25 @@ xfdesktop_settings_dialog_setup_tabs(GtkBuilder *main_gxml,
     /* We have to force wnck to initialize */
     wnck_screen = wnck_screen_get(panel->screen);
     wnck_screen_force_update(wnck_screen);
-    wnck_window = wnck_window_get(GDK_WINDOW_XID(gtk_widget_get_window(appearance_container)));
+    panel->wnck_window = wnck_window_get(window_xid);
+
+    if(panel->wnck_window == NULL)
+        panel->wnck_window = wnck_screen_get_active_window(wnck_screen);
 
-    g_signal_connect(wnck_window, "geometry-changed",
+    /* These callbacks are for updating the image_iconview when the window
+     * moves to another monitor or workspace */
+    g_signal_connect(panel->wnck_window, "geometry-changed",
                      G_CALLBACK(cb_update_background_tab), panel);
+    g_signal_connect(panel->wnck_window, "workspace-changed",
+                     G_CALLBACK(cb_update_background_tab), panel);
+    g_signal_connect(wnck_screen, "workspace-created",
+                     G_CALLBACK(cb_workspace_changed), panel);
+    g_signal_connect(wnck_screen, "workspace-destroyed",
+                     G_CALLBACK(cb_workspace_changed), panel);
+    g_signal_connect(wnck_screen, "active-workspace-changed",
+                    G_CALLBACK(cb_workspace_changed), panel);
+    g_signal_connect(G_OBJECT(screen), "monitors-changed",
+                     G_CALLBACK(cb_monitor_changed), panel);
 
     /* send invalid numbers so that the update_background_tab will update everything */
     panel->monitor = -1;
@@ -975,25 +1401,6 @@ xfdesktop_settings_dialog_setup_tabs(GtkBuilder *main_gxml,
     gtk_table_attach_defaults(GTK_TABLE(appearance_container),
                              appearance_settings, 0,1,0,1);
 
-    panel->image_style_combo = GTK_WIDGET(gtk_builder_get_object(appearance_gxml, "combo_style"));
-
-    panel->color_style_combo = GTK_WIDGET(gtk_builder_get_object(appearance_gxml,
-                                                                 "combo_colors"));
-
-    /* Pick the first entries so something shows up */
-    gtk_combo_box_set_active(GTK_COMBO_BOX(panel->image_style_combo), 0);
-    gtk_combo_box_set_active(GTK_COMBO_BOX(panel->color_style_combo), 0);
-
-    g_signal_connect(G_OBJECT(panel->color_style_combo), "changed",
-                     G_CALLBACK(cb_xfdesktop_combo_color_changed),
-                     panel);
-
-    panel->color1_btn = GTK_WIDGET(gtk_builder_get_object(appearance_gxml,
-                                                          "color1_btn"));
-
-    panel->color2_btn = GTK_WIDGET(gtk_builder_get_object(appearance_gxml,
-                                                          "color2_btn"));
-
     /* icon view area */
     panel->frame_image_list = GTK_WIDGET(gtk_builder_get_object(appearance_gxml,
                                                                 "frame_image_list"));
@@ -1012,6 +1419,42 @@ xfdesktop_settings_dialog_setup_tabs(GtkBuilder *main_gxml,
     gtk_file_filter_add_pixbuf_formats(filter);
     gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(panel->btn_folder), filter);
 
+    /* Image and color style options */
+    panel->image_style_combo = GTK_WIDGET(gtk_builder_get_object(appearance_gxml, "combo_style"));
+
+    panel->color_style_combo = GTK_WIDGET(gtk_builder_get_object(appearance_gxml,
+                                                                 "combo_colors"));
+
+    panel->color1_btn = GTK_WIDGET(gtk_builder_get_object(appearance_gxml,
+                                                          "color1_btn"));
+
+    panel->color2_btn = GTK_WIDGET(gtk_builder_get_object(appearance_gxml,
+                                                          "color2_btn"));
+
+    g_signal_connect(G_OBJECT(panel->image_style_combo), "changed",
+                     G_CALLBACK(cb_xfdesktop_combo_image_style_changed),
+                     panel);
+
+    g_signal_connect(G_OBJECT(panel->color_style_combo), "changed",
+                     G_CALLBACK(cb_xfdesktop_combo_color_changed),
+                     panel);
+
+    /* Pick the first entries so something shows up */
+    gtk_combo_box_set_active(GTK_COMBO_BOX(panel->image_style_combo), XFCE_BACKDROP_IMAGE_SCALED);
+    gtk_combo_box_set_active(GTK_COMBO_BOX(panel->color_style_combo), 0);
+
+    /* Use these settings for all workspaces checkbox */
+    panel->chk_apply_to_all =  GTK_WIDGET(gtk_builder_get_object(appearance_gxml,
+                                                                 "chk_apply_to_all"));
+
+    if(xfconf_channel_get_bool(channel, SINGLE_WORKSPACE_MODE, TRUE)) {
+        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(panel->chk_apply_to_all), TRUE);
+    }
+
+    g_signal_connect(G_OBJECT(panel->chk_apply_to_all), "toggled",
+                    G_CALLBACK(cb_xfdesktop_chk_apply_to_all),
+                    panel);
+
     /* background cycle timer */
     panel->backdrop_cycle_chkbox = GTK_WIDGET(gtk_builder_get_object(appearance_gxml,
                                                                      "chk_cycle_backdrop"));
@@ -1094,6 +1537,7 @@ xfdesktop_settings_dialog_setup_tabs(GtkBuilder *main_gxml,
                            "active");
 
     setup_special_icon_list(main_gxml, channel);
+    cb_update_background_tab(panel->wnck_window, panel);
 }
 
 static void
@@ -1118,11 +1562,12 @@ main(int argc, char **argv)
 {
     XfconfChannel *channel;
     GtkBuilder *gxml;
-    GtkWidget *dialog;
     GError *error = NULL;
 
     xfce_textdomain(GETTEXT_PACKAGE, LOCALEDIR, "UTF-8");
 
+    gdk_threads_init();
+
     if(!gtk_init_with_args(&argc, &argv, "", option_entries, PACKAGE, &error)) {
         if(G_LIKELY(error)) {
             g_printerr("%s: %s.\n", G_LOG_DOMAIN, error->message);
@@ -1137,7 +1582,7 @@ main(int argc, char **argv)
 
     if(G_UNLIKELY(opt_version)) {
         g_print("%s %s (Xfce %s)\n\n", G_LOG_DOMAIN, VERSION, xfce_version_string());
-        g_print("%s\n", "Copyright (c) 2004-2008");
+        g_print("%s\n", "Copyright (c) 2004-2013");
         g_print("\t%s\n\n", _("The Xfce development team. All rights reserved."));
         g_print(_("Please report bugs to <%s>."), PACKAGE_BUGREPORT);
         g_print("\n");
@@ -1170,12 +1615,14 @@ main(int argc, char **argv)
     channel = xfconf_channel_new(XFDESKTOP_CHANNEL);
 
     if(opt_socket_id == 0) {
+        GtkWidget *dialog;
         dialog = GTK_WIDGET(gtk_builder_get_object(gxml, "prefs_dialog"));
         g_signal_connect(dialog, "response",
                          G_CALLBACK(xfdesktop_settings_response), NULL);
         gtk_window_present(GTK_WINDOW (dialog));
         xfdesktop_settings_dialog_setup_tabs(gxml, channel,
-                                             gtk_widget_get_screen(dialog));
+                                             gtk_widget_get_screen(dialog),
+                                             GDK_WINDOW_XID(gtk_widget_get_window(dialog)));
 
         /* To prevent the settings dialog to be saved in the session */
         gdk_x11_set_sm_client_id("FAKE ID");
@@ -1188,14 +1635,15 @@ main(int argc, char **argv)
         gtk_widget_show(plug);
         g_signal_connect(G_OBJECT(plug), "delete-event",
                          G_CALLBACK(gtk_main_quit), NULL);
-        xfdesktop_settings_dialog_setup_tabs(gxml, channel,
-                                             gtk_widget_get_screen(plug));
 
         gdk_notify_startup_complete();
 
         plug_child = GTK_WIDGET(gtk_builder_get_object(gxml, "alignment1"));
         gtk_widget_reparent(plug_child, plug);
         gtk_widget_show(plug_child);
+        xfdesktop_settings_dialog_setup_tabs(gxml, channel,
+                                             gtk_widget_get_screen(plug),
+                                             GDK_WINDOW_XID(gtk_widget_get_window(plug_child)));
 
         gtk_main();
     }
diff --git a/settings/xfdesktop-settings-appearance-frame-ui.glade b/settings/xfdesktop-settings-appearance-frame-ui.glade
index 9a5ac56..32e10c0 100644
--- a/settings/xfdesktop-settings-appearance-frame-ui.glade
+++ b/settings/xfdesktop-settings-appearance-frame-ui.glade
@@ -34,245 +34,297 @@
     <property name="border_width">12</property>
     <property name="left_padding">6</property>
     <child>
-      <object class="GtkVBox" id="vbox1">
+      <object class="GtkFrame" id="frame_image_list">
         <property name="visible">True</property>
-        <property name="spacing">6</property>
+        <property name="label_xalign">0</property>
+        <property name="shadow_type">GTK_SHADOW_NONE</property>
         <child>
-          <object class="GtkHBox" id="hbox1">
+          <object class="GtkAlignment" id="top_padding_alignment">
             <property name="visible">True</property>
-            <property name="spacing">12</property>
+            <property name="top_padding">6</property>
             <child>
-              <object class="GtkFrame" id="frame_image_list">
+              <object class="GtkVBox" id="background_tab_vbox">
                 <property name="visible">True</property>
-                <property name="label_xalign">0</property>
-                <property name="shadow_type">GTK_SHADOW_NONE</property>
+                <property name="spacing">6</property>
                 <child>
-                  <object class="GtkAlignment" id="alignment7">
+                  <object class="GtkScrolledWindow" id="iconview_imagelist_scrolled_window">
                     <property name="visible">True</property>
-                    <property name="top_padding">6</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="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+                    <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+                    <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
                     <child>
-                      <object class="GtkVBox" id="vbox3">
+                      <object class="GtkIconView" id="iconview_imagelist">
                         <property name="visible">True</property>
-                        <property name="spacing">6</property>
-                        <child>
-                          <object class="GtkScrolledWindow" id="scrolledwindow1">
-                            <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="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
-                            <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
-                            <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
-                            <child>
-                              <object class="GtkIconView" id="iconview_imagelist">
-                                <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>
-                              </object>
-                            </child>
-                          </object>
-                        </child>
+                        <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>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">True</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkTable" id="folder_color_and_image_style_table">
+                    <property name="visible">True</property>
+                    <property name="n-columns">8</property>
+                    <property name="n-rows">2</property>
+                    <property name="row-spacing">6</property>
+                    <property name="column-spacing">12</property>
+                    <child>
+                      <object class="GtkLabel" id="label_folder">
+                        <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="label" translatable="yes">Folder:</property>
+                        <property name="use_underline">True</property>
+                      </object>
+                      <packing>
+                        <property name="left-attach">0</property>
+                        <property name="right-attach">1</property>
+                        <property name="top-attach">0</property>
+                        <property name="bottom-attach">1</property>
+                        <property name="x-options">GTK_SHRINK</property>
+                        <property name="y-options">GTK_SHRINK</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkFileChooserButton" id="btn_folder">
+                        <property name="visible">True</property>
+                        <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="action">GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER</property>
+                      </object>
+                      <packing>
+                        <property name="left-attach">1</property>
+                        <property name="right-attach">2</property>
+                        <property name="top-attach">0</property>
+                        <property name="bottom-attach">1</property>
+                        <property name="x-options">GTK_FILL|GTK_EXPAND</property>
+                        <property name="y-options">GTK_SHRINK</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkAlignment" id="alignment_spacer">
+                        <property name="visible">True</property>
+                      </object>
+                      <packing>
+                        <property name="left-attach">4</property>
+                        <property name="right-attach">5</property>
+                        <property name="top-attach">0</property>
+                        <property name="bottom-attach">1</property>
+                        <property name="x-options">GTK_FILL|GTK_EXPAND</property>
+                        <property name="y-options">GTK_SHRINK</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkLabel" id="label_style">
+                        <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="label" translatable="yes">St_yle:</property>
+                        <property name="use_underline">True</property>
+                        <property name="mnemonic_widget">combo_style</property>
+                      </object>
+                      <packing>
+                        <property name="left-attach">5</property>
+                        <property name="right-attach">6</property>
+                        <property name="top-attach">0</property>
+                        <property name="bottom-attach">1</property>
+                        <property name="x-options">GTK_SHRINK</property>
+                        <property name="y-options">GTK_SHRINK</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkComboBoxText" id="combo_style">
+                        <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>
+                          <item translatable="yes">Tiled</item>
+                          <item translatable="yes">Stretched</item>
+                          <item translatable="yes">Scaled</item>
+                          <item translatable="yes">Zoomed</item>
+                          <item translatable="yes">Spanning Screens</item>
+                        </items>
+                      </object>
+                      <packing>
+                        <property name="left-attach">6</property>
+                        <property name="right-attach">7</property>
+                        <property name="top-attach">0</property>
+                        <property name="bottom-attach">1</property>
+                        <property name="x-options">GTK_FILL</property>
+                        <property name="y-options">GTK_SHRINK</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkLabel" id="label_color">
+                        <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="label" translatable="yes">Color:</property>
+                        <property name="use_underline">True</property>
+                      </object>
+                      <packing>
+                        <property name="left-attach">0</property>
+                        <property name="right-attach">1</property>
+                        <property name="top-attach">1</property>
+                        <property name="bottom-attach">2</property>
+                        <property name="x-options">GTK_SHRINK</property>
+                        <property name="y-options">GTK_SHRINK</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkComboBox" id="combo_colors">
+                        <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="GtkHBox" id="hbox3">
-                            <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">3</property>
-                            <child>
-                              <object class="GtkLabel" id="label_folder">
-                                <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="label" translatable="yes">Folder:</property>
-                                <property name="use_underline">True</property>
-                              </object>
-                              <packing>
-                                <property name="expand">False</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkAlignment" id="alignment_btn_folder">
-                                <property name="visible">True</property>
-                                <property name="xalign">0.0</property>
-                                <property name="xscale">0.5</property>
-                                <child>
-                                  <object class="GtkFileChooserButton" id="btn_folder">
-                                    <property name="visible">True</property>
-                                    <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="action">GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER</property>
-                                  </object>
-                                </child>
-                              </object>
-                            </child>
-                            <child>
-                              <object class="GtkComboBoxText" id="combo_style">
-                                <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>
-                                  <item translatable="yes">Tiled</item>
-                                  <item translatable="yes">Stretched</item>
-                                  <item translatable="yes">Scaled</item>
-                                  <item translatable="yes">Zoomed</item>
-                                </items>
-                              </object>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="pack-type">GTK_PACK_END</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkLabel" id="label_style">
-                                <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="label" translatable="yes">St_yle:</property>
-                                <property name="use_underline">True</property>
-                                <property name="mnemonic_widget">combo_style</property>
-                              </object>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="pack-type">GTK_PACK_END</property>
-                              </packing>
-                            </child>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="position">1</property>
-                          </packing>
+                          <object class="GtkCellRendererText" id="renderer2"/>
+                          <attributes>
+                            <attribute name="text">0</attribute>
+                          </attributes>
                         </child>
                       </object>
+                      <packing>
+                        <property name="left-attach">1</property>
+                        <property name="right-attach">2</property>
+                        <property name="top-attach">1</property>
+                        <property name="bottom-attach">2</property>
+                        <property name="x-options">GTK_FILL|GTK_EXPAND</property>
+                        <property name="y-options">GTK_SHRINK</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkColorButton" id="color1_btn">
+                        <property name="visible">True</property>
+                        <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_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                        <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>
+                        <property name="right-attach">3</property>
+                        <property name="top-attach">1</property>
+                        <property name="bottom-attach">2</property>
+                        <property name="x-options">GTK_SHRINK</property>
+                        <property name="y-options">GTK_SHRINK</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkColorButton" id="color2_btn">
+                        <property name="visible">True</property>
+                        <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_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                        <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>
+                        <property name="right-attach">4</property>
+                        <property name="top-attach">1</property>
+                        <property name="bottom-attach">2</property>
+                        <property name="x-options">GTK_SHRINK</property>
+                        <property name="y-options">GTK_SHRINK</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkCheckButton" id="chk_apply_to_all">
+                        <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="label" translatable="yes">Apply to all _workspaces</property>
+                        <property name="use_underline">True</property>
+                        <property name="draw_indicator">True</property>
+                      </object>
+                      <packing>
+                        <property name="left-attach">6</property>
+                        <property name="right-attach">7</property>
+                        <property name="top-attach">1</property>
+                        <property name="bottom-attach">2</property>
+                        <property name="x-options">GTK_SHRINK</property>
+                        <property name="y-options">GTK_SHRINK</property>
+                      </packing>
                     </child>
                   </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="position">1</property>
+                  </packing>
                 </child>
-              </object>
-            </child>
-          </object>
-        </child>
-        <child>
-          <object class="GtkHBox" id="hbox_colors">
-            <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>
-            <child>
-              <object class="GtkLabel" id="label_color">
-                <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="label" translatable="yes">Color:</property>
-                <property name="use_underline">True</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkComboBox" id="combo_colors">
-                <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"/>
-                  <attributes>
-                    <attribute name="text">0</attribute>
-                  </attributes>
+                  <object class="GtkHBox" id="cycle_options_hbox">
+                    <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">12</property>
+                    <child>
+                      <object class="GtkCheckButton" id="chk_cycle_backdrop">
+                        <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="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="use_underline">True</property>
+                        <property name="draw_indicator">True</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkSpinButton" id="spin_backdrop_time_minutes">
+                        <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>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="position">2</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkCheckButton" id="chk_random_backdrop_order">
+                        <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="label" translatable="yes">_Random Order</property>
+                        <property name="use_underline">True</property>
+                        <property name="draw_indicator">True</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                      </packing>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="position">2</property>
+                  </packing>
                 </child>
               </object>
-              <packing>
-                <property name="expand">False</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkColorButton" id="color1_btn">
-                <property name="visible">True</property>
-                <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_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <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="expand">False</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkColorButton" id="color2_btn">
-                <property name="visible">True</property>
-                <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_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <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="expand">False</property>
-              </packing>
             </child>
           </object>
-          <packing>
-            <property name="expand">False</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>
-            <property name="spacing">4</property>
-            <child>
-              <object class="GtkCheckButton" id="chk_cycle_backdrop">
-                <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="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="use_underline">True</property>
-                <property name="draw_indicator">True</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-              </packing>
-            </child>
-          <child>
-            <object class="GtkSpinButton" id="spin_backdrop_time_minutes">
-              <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>
-            </object>
-            <packing>
-              <property name="expand">False</property>
-              <property name="position">2</property>
-            </packing>
-          </child>
-          <child>
-            <object class="GtkCheckButton" id="chk_random_backdrop_order">
-              <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="label" translatable="yes">_Random Order</property>
-              <property name="use_underline">True</property>
-              <property name="draw_indicator">True</property>
-            </object>
-            <packing>
-              <property name="expand">False</property>
-            </packing>
-          </child>
-        </object>
-        <packing>
-          <property name="expand">False</property>
-          <property name="position">2</property>
-        </packing>
-      </child>
       </object>
     </child>
   </object>
diff --git a/settings/xfdesktop-settings-ui.glade b/settings/xfdesktop-settings-ui.glade
index 7bccb6b..b69fe4b 100644
--- a/settings/xfdesktop-settings-ui.glade
+++ b/settings/xfdesktop-settings-ui.glade
@@ -769,7 +769,7 @@
               </object>
             </child>
             <child>
-              <object class="GtkButton" id="button1">
+              <object class="GtkButton" id="bnt_exit">
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
                 <property name="receives_default">True</property>
@@ -791,7 +791,7 @@
     </child>
     <action-widgets>
       <action-widget response="-11">button2</action-widget>
-      <action-widget response="-3">button1</action-widget>
+      <action-widget response="-3">bnt_exit</action-widget>
     </action-widgets>
   </object>
 </interface>
diff --git a/src/xfce-backdrop.c b/src/xfce-backdrop.c
index a2bd53b..a8aa834 100644
--- a/src/xfce-backdrop.c
+++ b/src/xfce-backdrop.c
@@ -60,7 +60,9 @@ struct _XfceBackdropPriv
 {
     gint width, height;
     gint bpp;
-    
+
+    GdkPixbuf *pix;
+
     XfceBackdropColorStyle color_style;
     GdkColor color1;
     GdkColor color2;
@@ -68,8 +70,6 @@ struct _XfceBackdropPriv
     XfceBackdropImageStyle image_style;
     gchar *image_path;
 
-    gint brightness;
-
     gboolean cycle_backdrop;
     guint cycle_timer;
     guint cycle_timer_id;
@@ -102,52 +102,6 @@ static guint backdrop_signals[LAST_SIGNAL] = { 0, };
 /* helper functions */
 
 static GdkPixbuf *
-adjust_brightness(GdkPixbuf *src, gint amount)
-{
-    GdkPixbuf *newpix;
-    GdkPixdata pdata;
-    gboolean has_alpha = FALSE;
-    gint i, len;
-    GError *err = NULL;
-    
-    g_return_val_if_fail(src != NULL, NULL);
-    if(amount == 0)
-        return src;
-    
-    gdk_pixdata_from_pixbuf(&pdata, src, FALSE);
-    has_alpha = (pdata.pixdata_type & GDK_PIXDATA_COLOR_TYPE_RGBA);
-    if(pdata.length < 1)
-        len = pdata.width * pdata.height * (has_alpha?4:3);
-    else
-        len = pdata.length - GDK_PIXDATA_HEADER_LENGTH;
-    
-    for(i = 0; i < len; i++) {
-        gshort scaled;
-        
-        if(has_alpha && (i+1)%4)
-            continue;
-        
-        scaled = pdata.pixel_data[i] + amount;
-        if(scaled > 255)
-            scaled = 255;
-        if(scaled < 0)
-            scaled = 0;
-        pdata.pixel_data[i] = scaled;
-    }
-    
-    newpix = gdk_pixbuf_from_pixdata(&pdata, TRUE, &err);
-    if(!newpix) {
-        g_warning("%s: Unable to modify image brightness: %s", PACKAGE,
-                err->message);
-        g_error_free(err);
-        return src;
-    }
-    g_object_unref(G_OBJECT(src));
-    
-    return newpix;
-}
-
-static GdkPixbuf *
 create_solid(GdkColor *color,
              gint width,
              gint height,
@@ -227,6 +181,19 @@ create_gradient(GdkColor *color1, GdkColor *color2, gint width, gint height,
     return pix;
 }
 
+static void
+xfce_backdrop_clear_cached_image(XfceBackdrop *backdrop)
+{
+    g_return_if_fail(XFCE_IS_BACKDROP(backdrop));
+
+    if(backdrop->priv->pix == NULL)
+        return;
+
+    g_object_unref(backdrop->priv->pix);
+    backdrop->priv->pix = NULL;
+}
+
+
 /* gobject-related functions */
 
 
@@ -296,13 +263,6 @@ xfce_backdrop_class_init(XfceBackdropClass *klass)
                                                         DEFAULT_BACKDROP,
                                                         XFDESKTOP_PARAM_FLAGS));
 
-    g_object_class_install_property(gobject_class, PROP_BRIGHTNESS,
-                                    g_param_spec_int("brightness",
-                                                     "brightness",
-                                                     "brightness",
-                                                     -128, 127, 0,
-                                                     XFDESKTOP_PARAM_FLAGS));
-
     g_object_class_install_property(gobject_class, PROP_BACKDROP_CYCLE_ENABLE,
                                     g_param_spec_boolean("backdrop-cycle-enable",
                                                          "backdrop-cycle-enable",
@@ -358,6 +318,8 @@ xfce_backdrop_finalize(GObject *object)
         backdrop->priv->cycle_timer_id = 0;
     }
 
+    xfce_backdrop_clear_cached_image(backdrop);
+
     G_OBJECT_CLASS(xfce_backdrop_parent_class)->finalize(object);
 }
 
@@ -396,10 +358,6 @@ xfce_backdrop_set_property(GObject *object,
                                              g_value_get_string(value));
             break;
 
-        case PROP_BRIGHTNESS:
-            xfce_backdrop_set_brightness(backdrop, g_value_get_int(value));
-            break;
-
         case PROP_BACKDROP_CYCLE_ENABLE:
             xfce_backdrop_set_cycle_backdrop(backdrop, g_value_get_boolean(value));
             break;
@@ -448,10 +406,6 @@ xfce_backdrop_get_property(GObject *object,
                                xfce_backdrop_get_image_filename(backdrop));
             break;
 
-        case PROP_BRIGHTNESS:
-            g_value_set_int(value, xfce_backdrop_get_brightness(backdrop));
-            break;
-
         case PROP_BACKDROP_CYCLE_ENABLE:
             g_value_set_boolean(value, xfce_backdrop_get_cycle_backdrop(backdrop));
             break;
@@ -537,9 +491,13 @@ void
 xfce_backdrop_set_size(XfceBackdrop *backdrop, gint width, gint height)
 {
     g_return_if_fail(XFCE_IS_BACKDROP(backdrop));
-    
-    backdrop->priv->width = width;
-    backdrop->priv->height = height;
+
+    if(backdrop->priv->width != width ||
+       backdrop->priv->height != height) {
+        xfce_backdrop_clear_cached_image(backdrop);
+        backdrop->priv->width = width;
+        backdrop->priv->height = height;
+    }
 }
 
 /**
@@ -557,6 +515,7 @@ xfce_backdrop_set_color_style(XfceBackdrop *backdrop,
     g_return_if_fail((int)style >= 0 && style <= XFCE_BACKDROP_COLOR_TRANSPARENT);
     
     if(style != backdrop->priv->color_style) {
+        xfce_backdrop_clear_cached_image(backdrop);
         backdrop->priv->color_style = style;
         g_signal_emit(G_OBJECT(backdrop), backdrop_signals[BACKDROP_CHANGED], 0);
     }
@@ -591,6 +550,7 @@ xfce_backdrop_set_first_color(XfceBackdrop *backdrop,
             || color->green != backdrop->priv->color1.green
             || color->blue != backdrop->priv->color1.blue)
     {
+        xfce_backdrop_clear_cached_image(backdrop);
         backdrop->priv->color1.red = color->red;
         backdrop->priv->color1.green = color->green;
         backdrop->priv->color1.blue = color->blue;
@@ -627,6 +587,7 @@ xfce_backdrop_set_second_color(XfceBackdrop *backdrop,
             || color->green != backdrop->priv->color2.green
             || color->blue != backdrop->priv->color2.blue)
     {
+        xfce_backdrop_clear_cached_image(backdrop);
         backdrop->priv->color2.red = color->red;
         backdrop->priv->color2.green = color->green;
         backdrop->priv->color2.blue = color->blue;
@@ -662,6 +623,7 @@ xfce_backdrop_set_image_style(XfceBackdrop *backdrop,
     g_return_if_fail(XFCE_IS_BACKDROP(backdrop));
     
     if(style != backdrop->priv->image_style) {
+        xfce_backdrop_clear_cached_image(backdrop);
         backdrop->priv->image_style = style;
         g_signal_emit(G_OBJECT(backdrop), backdrop_signals[BACKDROP_CHANGED], 0);
     }
@@ -697,7 +659,9 @@ xfce_backdrop_set_image_filename(XfceBackdrop *backdrop, const gchar *filename)
         backdrop->priv->image_path = g_strdup(filename);
     else
         backdrop->priv->image_path = NULL;
-    
+
+    xfce_backdrop_clear_cached_image(backdrop);
+
     g_signal_emit(G_OBJECT(backdrop), backdrop_signals[BACKDROP_CHANGED], 0);
 }
 
@@ -708,33 +672,6 @@ xfce_backdrop_get_image_filename(XfceBackdrop *backdrop)
     return backdrop->priv->image_path;
 }
 
-/**
- * xfce_backdrop_set_brightness:
- * @backdrop: An #XfceBackdrop.
- * @brightness: A brightness value.
- *
- * Modifies the brightness of the backdrop using a value between -128 and 127.
- * A value of 0 indicates that the brightness should not be changed.  This value
- * is applied to the entire image, after compositing.
- **/
-void
-xfce_backdrop_set_brightness(XfceBackdrop *backdrop, gint brightness)
-{
-    g_return_if_fail(XFCE_IS_BACKDROP(backdrop));
-    
-    if(brightness != backdrop->priv->brightness) {
-        backdrop->priv->brightness = brightness;
-        g_signal_emit(G_OBJECT(backdrop), backdrop_signals[BACKDROP_CHANGED], 0);
-    }
-}
-
-gint
-xfce_backdrop_get_brightness(XfceBackdrop *backdrop)
-{
-    g_return_val_if_fail(XFCE_IS_BACKDROP(backdrop), 0);
-    return backdrop->priv->brightness;
-}
-
 static gboolean
 xfce_backdrop_timer(XfceBackdrop *backdrop)
 {
@@ -742,7 +679,9 @@ xfce_backdrop_timer(XfceBackdrop *backdrop)
 
     g_return_val_if_fail(XFCE_IS_BACKDROP(backdrop), FALSE);
 
-    g_signal_emit(G_OBJECT(backdrop), backdrop_signals[BACKDROP_CYCLE], 0);
+    /* 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);
 
     return TRUE;
 }
@@ -853,9 +792,16 @@ xfce_backdrop_get_pixbuf(XfceBackdrop *backdrop)
     gint dx, dy, xo, yo;
     gdouble xscale, yscale;
     GdkInterpType interp;
-    
+
+    TRACE("entering");
+
     g_return_val_if_fail(XFCE_IS_BACKDROP(backdrop), NULL);
-    
+
+    if(backdrop->priv->pix != NULL) {
+        DBG("pixbuf cached");
+        return g_object_ref(backdrop->priv->pix);
+    }
+
     if(backdrop->priv->image_style != XFCE_BACKDROP_IMAGE_NONE &&
        backdrop->priv->image_path) {
         format = gdk_pixbuf_get_file_info(backdrop->priv->image_path, &iw, &ih);
@@ -884,12 +830,8 @@ xfce_backdrop_get_pixbuf(XfceBackdrop *backdrop)
             final_image = create_solid(&backdrop->priv->color1, w, h, FALSE, 0xff);
     }
     
-    if(!apply_backdrop_image) {
-        if(backdrop->priv->brightness != 0)
-            final_image = adjust_brightness(final_image, backdrop->priv->brightness);
-        
+    if(!apply_backdrop_image)
         return final_image;
-    }
     
     istyle = backdrop->priv->image_style;
     
@@ -929,6 +871,12 @@ xfce_backdrop_get_pixbuf(XfceBackdrop *backdrop)
         case XFCE_BACKDROP_IMAGE_TILED:
             image = gdk_pixbuf_new_from_file(backdrop->priv->image_path, NULL);
             tmp = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, w, h);
+            /* Now that the image has been loaded, recalculate the image
+             * size because gdk_pixbuf_get_file_info doesn't always return
+             * the correct size */
+            iw = gdk_pixbuf_get_width(image);
+            ih = gdk_pixbuf_get_height(image);
+
             for(i = 0; (i * iw) < w; i++) {
                 for(j = 0; (j * ih) < h; j++) {
                     gint newx = iw * i, newy = ih * j;
@@ -938,7 +886,7 @@ xfce_backdrop_get_pixbuf(XfceBackdrop *backdrop)
                         neww = w - newx;
                     if((newy + newh) > h)
                         newh = h - newy;
-                    
+
                     gdk_pixbuf_copy_area(image, 0, 0,
                             neww, newh, tmp, newx, newy);
                 }
@@ -950,7 +898,6 @@ xfce_backdrop_get_pixbuf(XfceBackdrop *backdrop)
             break;
         
         case XFCE_BACKDROP_IMAGE_STRETCHED:
-        case XFCE_BACKDROP_IMAGE_SPANNING_SCREENS:
             image = gdk_pixbuf_new_from_file_at_scale(
                             backdrop->priv->image_path, w, h, FALSE, NULL);
             gdk_pixbuf_composite(image, final_image, 0, 0, w, h,
@@ -981,6 +928,7 @@ xfce_backdrop_get_pixbuf(XfceBackdrop *backdrop)
             break;
         
         case XFCE_BACKDROP_IMAGE_ZOOMED:
+        case XFCE_BACKDROP_IMAGE_SPANNING_SCREENS:
             xscale = (gdouble)w / iw;
             yscale = (gdouble)h / ih;
             if(xscale < yscale) {
@@ -1006,9 +954,53 @@ xfce_backdrop_get_pixbuf(XfceBackdrop *backdrop)
     
     if(image)
         g_object_unref(G_OBJECT(image));
-    
-    if(backdrop->priv->brightness != 0)
-        final_image = adjust_brightness(final_image, backdrop->priv->brightness);
-    
+
+    /* cache it */
+    backdrop->priv->pix = g_object_ref(final_image);
+
     return final_image;
 }
+
+/* returns TRUE if they have identical settings. */
+gboolean xfce_backdrop_compare_backdrops(XfceBackdrop *backdrop_a,
+                                         XfceBackdrop *backdrop_b)
+{
+    if(g_strcmp0(backdrop_a->priv->image_path, backdrop_b->priv->image_path) != 0) {
+        DBG("filename different");
+        return FALSE;
+    }
+
+    if(backdrop_a->priv->image_style != backdrop_b->priv->image_style) {
+        DBG("image_style different");
+        return FALSE;
+    }
+
+    if(backdrop_a->priv->color_style != backdrop_b->priv->color_style) {
+        DBG("color_style different");
+        return FALSE;
+    }
+
+    /* Every color style uses color1 except for transparent which does not need
+     * a color check */
+    if(backdrop_a->priv->color_style != XFCE_BACKDROP_COLOR_TRANSPARENT &&
+       !gdk_color_equal(&backdrop_a->priv->color1, &backdrop_b->priv->color1)) {
+        DBG("colors different");
+        return FALSE;
+    }
+
+    /* When the style is set to gradient then we should check color2 as well */
+    if((backdrop_a->priv->color_style == XFCE_BACKDROP_COLOR_HORIZ_GRADIENT ||
+        backdrop_a->priv->color_style == XFCE_BACKDROP_COLOR_VERT_GRADIENT) &&
+       !gdk_color_equal(&backdrop_a->priv->color2, &backdrop_b->priv->color2)) {
+        DBG("colors different");
+        return FALSE;
+    }
+
+    if(backdrop_a->priv->cycle_backdrop != backdrop_b->priv->cycle_backdrop ||
+       backdrop_a->priv->cycle_backdrop == TRUE) {
+        DBG("backdrop cycle different");
+        return FALSE;
+    }
+
+    return TRUE;
+}
diff --git a/src/xfce-backdrop.h b/src/xfce-backdrop.h
index 6c013c3..ab26d45 100644
--- a/src/xfce-backdrop.h
+++ b/src/xfce-backdrop.h
@@ -111,11 +111,6 @@ void xfce_backdrop_set_image_filename    (XfceBackdrop *backdrop,
 G_CONST_RETURN gchar *xfce_backdrop_get_image_filename
                                          (XfceBackdrop *backdrop);
 
-
-void xfce_backdrop_set_brightness        (XfceBackdrop *backdrop,
-                                          gint brightness);
-gint xfce_backdrop_get_brightness        (XfceBackdrop *backdrop);
-
 void xfce_backdrop_set_cycle_backdrop    (XfceBackdrop *backdrop,
                                           gboolean cycle_backdrop);
 gboolean xfce_backdrop_get_cycle_backdrop(XfceBackdrop *backdrop);
@@ -130,6 +125,9 @@ gboolean xfce_backdrop_get_random_order  (XfceBackdrop *backdrop);
 
 GdkPixbuf *xfce_backdrop_get_pixbuf      (XfceBackdrop *backdrop);
 
+gboolean xfce_backdrop_compare_backdrops (XfceBackdrop *backdrop_a,
+                                          XfceBackdrop *backdrop_b);
+
 G_END_DECLS
 
 #endif
diff --git a/src/xfce-desktop.c b/src/xfce-desktop.c
index 95c30f6..149a833 100644
--- a/src/xfce-desktop.c
+++ b/src/xfce-desktop.c
@@ -101,7 +101,10 @@ struct _XfceDesktopPriv
     gint nworkspaces;
     XfceWorkspace **workspaces;
     gint current_workspace;
-    
+
+    gboolean single_workspace_mode;
+    gint single_workspace_num;
+
     SessionLogoutFunc session_logout_func;
     
 #ifdef ENABLE_DESKTOP_ICONS
@@ -130,6 +133,8 @@ enum
     PROP_ICON_FONT_SIZE,
     PROP_ICON_FONT_SIZE_SET,
 #endif
+    PROP_SINGLE_WORKSPACE_MODE,
+    PROP_SINGLE_WORKSPACE_NUMBER,
 };
 
 
@@ -156,6 +161,12 @@ static gboolean xfce_desktop_delete_event(GtkWidget *w,
 static void xfce_desktop_style_set(GtkWidget *w,
                                    GtkStyle *old_style);
 
+static void xfce_desktop_set_single_workspace_mode(XfceDesktop *desktop,
+                                                   gboolean single_workspace);
+static void xfce_desktop_set_single_workspace_number(XfceDesktop *desktop,
+                                                     gint workspace_num);
+
+static gboolean xfce_desktop_get_single_workspace_mode(XfceDesktop *desktop);
 static gint xfce_desktop_get_current_workspace(XfceDesktop *desktop);
 
 static guint signals[N_SIGNALS] = { 0, };
@@ -307,9 +318,8 @@ backdrop_changed_cb(XfceBackdrop *backdrop, gpointer user_data)
     XfceDesktop *desktop = XFCE_DESKTOP(user_data);
     GdkPixmap *pmap = desktop->priv->bg_pixmap;
     GdkScreen *gscreen = desktop->priv->gscreen;
-    cairo_t *cr;
-    GdkPixbuf *pix;
     GdkRectangle rect;
+    GdkRegion *clip_region = NULL;
     gint i, monitor = -1, current_workspace;
     
     TRACE("entering");
@@ -323,6 +333,7 @@ backdrop_changed_cb(XfceBackdrop *backdrop, gpointer user_data)
 
     current_workspace = xfce_desktop_get_current_workspace(desktop);
 
+    /* Find out which monitor the backdrop is on */
     for(i = 0; i < xfce_desktop_get_n_monitors(desktop); i++) {
         if(backdrop == xfce_workspace_get_backdrop(desktop->priv->workspaces[current_workspace], i)) {
             monitor = i;
@@ -336,13 +347,9 @@ backdrop_changed_cb(XfceBackdrop *backdrop, gpointer user_data)
     DBG("backdrop changed for workspace %d, monitor %d (%s)",
         current_workspace, monitor, gdk_screen_get_monitor_plug_name(gscreen, monitor));
 
-    /* create/get the composited backdrop pixmap */
-    pix = xfce_backdrop_get_pixbuf(backdrop);
-    if(!pix)
-        return;
-
     if(xfce_desktop_get_n_monitors(desktop) > 1
        && xfce_workspace_get_xinerama_stretch(desktop->priv->workspaces[current_workspace])) {
+        /* Spanning screens */
         GdkRectangle monitor_rect;
 
         gdk_screen_get_monitor_geometry(gscreen, 0, &rect);
@@ -360,26 +367,87 @@ backdrop_changed_cb(XfceBackdrop *backdrop, gpointer user_data)
 
         rect.width = gdk_screen_get_width(gscreen);
         rect.height = gdk_screen_get_height(gscreen);
+        DBG("xinerama_stretch x %d, y %d, width %d, height %d",
+            rect.x, rect.y, rect.width, rect.height);
     } else {
         gdk_screen_get_monitor_geometry(gscreen, monitor, &rect);
+        DBG("monitor x %d, y %d, width %d, height %d",
+            rect.x, rect.y, rect.width, rect.height);
     }
 
-    cr = gdk_cairo_create(GDK_DRAWABLE(pmap));
-    gdk_cairo_set_source_pixbuf(cr, pix, rect.x, rect.y);
-    cairo_paint(cr);
-    g_object_unref(G_OBJECT(pix));
-    cairo_destroy(cr);
-    
-    /* tell gtk to redraw the repainted area */
-    gtk_widget_queue_draw_area(GTK_WIDGET(desktop), rect.x, rect.y,
-                               rect.width, rect.height);
-    
-    set_imgfile_root_property(desktop,
-                              xfce_backdrop_get_image_filename(backdrop),
-                              monitor);
-    
-    /* do this again so apps watching the root win notice the update */
-    set_real_root_window_pixmap(gscreen, pmap);
+    xfce_backdrop_set_size(backdrop, rect.width, rect.height);
+
+    if(monitor > 0
+       && !xfce_workspace_get_xinerama_stretch(desktop->priv->workspaces[current_workspace])) {
+        clip_region = gdk_region_rectangle(&rect);
+
+        DBG("clip_region: x: %d, y: %d, w: %d, h: %d",
+            rect.x, rect.y, rect.width, rect.height);
+
+        /* If we are not monitor 0 on a multi-monitor setup we need to subtract
+         * all the previous monitor regions so we don't draw over them. This
+         * should prevent the overlap and double backdrop drawing bugs.
+         */
+        for(i = 0; i < monitor; i++) {
+            GdkRectangle previous_monitor;
+            GdkRegion *previous_region;
+            gdk_screen_get_monitor_geometry(gscreen, i, &previous_monitor);
+
+            DBG("previous_monitor: x: %d, y: %d, w: %d, h: %d",
+                previous_monitor.x, previous_monitor.y,
+                previous_monitor.width, previous_monitor.height);
+
+            previous_region = gdk_region_rectangle(&previous_monitor);
+
+            gdk_region_subtract(clip_region, previous_region);
+
+            gdk_region_destroy(previous_region);
+        }
+    }
+
+    if(clip_region != NULL) {
+        /* Update the area to redraw to limit the icons/area painted */
+        gdk_region_get_clipbox(clip_region, &rect);
+        DBG("area to update: x: %d, y: %d, w: %d, h: %d",
+            rect.x, rect.y, rect.width, rect.height);
+    }
+
+    if(rect.width != 0 && rect.height != 0) {
+        /* create/get the composited backdrop pixmap */
+        GdkPixbuf *pix = xfce_backdrop_get_pixbuf(backdrop);
+        cairo_t *cr;
+
+        if(!pix)
+            return;
+
+        cr = gdk_cairo_create(GDK_DRAWABLE(pmap));
+        gdk_cairo_set_source_pixbuf(cr, pix, rect.x, rect.y);
+
+        /* clip the area so we don't draw over a previous wallpaper */
+        if(clip_region != NULL) {
+            gdk_cairo_region(cr, clip_region);
+            cairo_clip(cr);
+        }
+
+        cairo_paint(cr);
+
+        /* tell gtk to redraw the repainted area */
+        gtk_widget_queue_draw_area(GTK_WIDGET(desktop), rect.x, rect.y,
+                                   rect.width, rect.height);
+
+        set_imgfile_root_property(desktop,
+                                  xfce_backdrop_get_image_filename(backdrop),
+                                  monitor);
+
+        /* do this again so apps watching the root win notice the update */
+        set_real_root_window_pixmap(gscreen, pmap);
+
+        g_object_unref(G_OBJECT(pix));
+        cairo_destroy(cr);
+    }
+
+    if(clip_region != NULL)
+        gdk_region_destroy(clip_region);
 }
 
 static void
@@ -387,12 +455,13 @@ screen_size_changed_cb(GdkScreen *gscreen, gpointer user_data)
 {
     XfceDesktop *desktop = user_data;
     gint w, h, current_workspace;
-    XfceBackdrop *current_backdrop;
 
     TRACE("entering");
 
     g_return_if_fail(XFCE_IS_DESKTOP(desktop));
-    g_return_if_fail(desktop->priv->workspaces);
+
+    if(desktop->priv->workspaces == NULL)
+        return;
     
     w = gdk_screen_get_width(gscreen);
     h = gdk_screen_get_height(gscreen);
@@ -413,19 +482,18 @@ screen_size_changed_cb(GdkScreen *gscreen, gpointer user_data)
     if(desktop->priv->nworkspaces <= current_workspace)
         return;
 
+    if(current_workspace < 0)
+        return;
+
     /* special case for 1 backdrop to handle xinerama stretching */
     if(xfce_workspace_get_xinerama_stretch(desktop->priv->workspaces[current_workspace])) {
-       xfce_backdrop_set_size(xfce_workspace_get_backdrop(desktop->priv->workspaces[current_workspace], 0), w, h);
        backdrop_changed_cb(xfce_workspace_get_backdrop(desktop->priv->workspaces[current_workspace], 0), desktop);
     } else {
-        GdkRectangle rect;
         gint i;
 
         for(i = 0; i < xfce_desktop_get_n_monitors(desktop); i++) {
-            gdk_screen_get_monitor_geometry(gscreen, i, &rect);
+            XfceBackdrop *current_backdrop;
             current_backdrop = xfce_workspace_get_backdrop(desktop->priv->workspaces[current_workspace], i);
-
-            xfce_backdrop_set_size(current_backdrop, rect.width, rect.height);
             backdrop_changed_cb(current_backdrop, desktop);
         }
     }
@@ -470,7 +538,7 @@ workspace_backdrop_changed_cb(XfceWorkspace *workspace,
 
     g_return_if_fail(XFCE_IS_WORKSPACE(workspace) && XFCE_IS_BACKDROP(backdrop));
 
-    if(desktop->priv->current_workspace == xfce_workspace_get_workspace_num(workspace))
+    if(xfce_desktop_get_current_workspace(desktop) == xfce_workspace_get_workspace_num(workspace))
         backdrop_changed_cb(backdrop, user_data);
 }
 
@@ -480,14 +548,43 @@ workspace_changed_cb(WnckScreen *wnck_screen,
                      gpointer user_data)
 {
     XfceDesktop *desktop = XFCE_DESKTOP(user_data);
-    WnckWorkspace *wnck_workspace = wnck_screen_get_active_workspace(wnck_screen);
+    gint current_workspace, new_workspace, i;
+    XfceBackdrop *current_backdrop, *new_backdrop;
 
     TRACE("entering");
 
-    desktop->priv->current_workspace = wnck_workspace_get_number(wnck_workspace);
+    current_workspace = desktop->priv->current_workspace;
+    new_workspace = xfce_desktop_get_current_workspace(desktop);
 
-    /* fake a screen size changed, so the background is properly set */
-    screen_size_changed_cb(desktop->priv->gscreen, user_data);
+    if(new_workspace < 0 || new_workspace >= desktop->priv->nworkspaces)
+        return;
+
+    desktop->priv->current_workspace = new_workspace;
+
+    DBG("current_workspace %d, new_workspace %d",
+        current_workspace, new_workspace);
+
+    for(i = 0; i < xfce_desktop_get_n_monitors(desktop); i++) {
+        /* We want to compare the current workspace backdrop with the new one
+         * and see if we can avoid changing them if they are the same image/style */
+        if(current_workspace < desktop->priv->nworkspaces) {
+            current_backdrop = xfce_workspace_get_backdrop(desktop->priv->workspaces[current_workspace], i);
+            new_backdrop = xfce_workspace_get_backdrop(desktop->priv->workspaces[new_workspace], i);
+
+            if(!xfce_backdrop_compare_backdrops(current_backdrop, new_backdrop)) {
+                /* only update monitors that require it */
+                backdrop_changed_cb(new_backdrop, user_data);
+            }
+        } else {
+            /* If current_workspace was removed, get the new backdrop and apply it */
+            new_backdrop = xfce_workspace_get_backdrop(desktop->priv->workspaces[new_workspace], i);
+            backdrop_changed_cb(new_backdrop, user_data);
+        }
+
+        /* When we're spanning screens we only care about the first monitor */
+        if(xfce_workspace_get_xinerama_stretch(desktop->priv->workspaces[new_workspace]))
+            break;
+    }
 }
 
 static void
@@ -549,6 +646,10 @@ workspace_destroyed_cb(WnckScreen *wnck_screen,
     /* deallocate it */
     desktop->priv->workspaces = g_realloc(desktop->priv->workspaces,
                                           desktop->priv->nworkspaces * sizeof(XfceWorkspace *));
+
+    /* Make sure we stay within bounds now that we removed a workspace */
+    if(desktop->priv->current_workspace > desktop->priv->nworkspaces)
+        desktop->priv->current_workspace = desktop->priv->nworkspaces;
 }
 
 static void
@@ -686,6 +787,20 @@ xfce_desktop_class_init(XfceDesktopClass *klass)
                                                          "icon font size set",
                                                          FALSE,
                                                          XFDESKTOP_PARAM_FLAGS));
+
+    g_object_class_install_property(gobject_class, PROP_SINGLE_WORKSPACE_MODE,
+                                    g_param_spec_boolean("single-workspace-mode",
+                                                         "single-workspace-mode",
+                                                         "single-workspace-mode",
+                                                         TRUE,
+                                                         XFDESKTOP_PARAM_FLAGS));
+
+    g_object_class_install_property(gobject_class, PROP_SINGLE_WORKSPACE_NUMBER,
+                                    g_param_spec_int("single-workspace-number",
+                                                     "single-workspace-number",
+                                                     "single-workspace-number",
+                                                     0, G_MAXINT16, 0,
+                                                     XFDESKTOP_PARAM_FLAGS));
 #endif
 #undef XFDESKTOP_PARAM_FLAGS
 }
@@ -743,6 +858,16 @@ xfce_desktop_set_property(GObject *object,
             break;
 
 #endif
+        case PROP_SINGLE_WORKSPACE_MODE:
+            xfce_desktop_set_single_workspace_mode(desktop,
+                                                   g_value_get_boolean(value));
+            break;
+
+        case PROP_SINGLE_WORKSPACE_NUMBER:
+            xfce_desktop_set_single_workspace_number(desktop,
+                                                     g_value_get_int(value));
+            break;
+
         default:
             G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
             break;
@@ -776,6 +901,14 @@ xfce_desktop_get_property(GObject *object,
             break;
 
 #endif
+        case PROP_SINGLE_WORKSPACE_MODE:
+            g_value_set_boolean(value, desktop->priv->single_workspace_mode);
+            break;
+
+        case PROP_SINGLE_WORKSPACE_NUMBER:
+            g_value_set_int(value, desktop->priv->single_workspace_num);
+            break;
+
         default:
             G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
             break;
@@ -791,7 +924,6 @@ xfce_desktop_realize(GtkWidget *widget)
     Window xid;
     GdkWindow *groot;
     WnckScreen *wnck_screen;
-    WnckWorkspace *wnck_workspace;
     
     TRACE("entering");
 
@@ -841,9 +973,16 @@ xfce_desktop_realize(GtkWidget *widget)
     wnck_screen_force_update(wnck_screen);
     desktop->priv->wnck_screen = wnck_screen;
 
+    xfconf_g_property_bind(desktop->priv->channel,
+                           SINGLE_WORKSPACE_MODE, G_TYPE_BOOLEAN,
+                           G_OBJECT(desktop), "single-workspace-mode");
+
+    xfconf_g_property_bind(desktop->priv->channel,
+                           SINGLE_WORKSPACE_NUMBER, G_TYPE_INT,
+                           G_OBJECT(desktop), "single-workspace-number");
+
     /* Get the current workspace number */
-    wnck_workspace = wnck_screen_get_active_workspace(wnck_screen);
-    desktop->priv->current_workspace = wnck_workspace_get_number(wnck_workspace);
+    desktop->priv->current_workspace = xfce_desktop_get_current_workspace(desktop);
     desktop->priv->nworkspaces = wnck_screen_get_workspace_count(wnck_screen);
 
     desktop->priv->workspaces = g_realloc(desktop->priv->workspaces,
@@ -1088,52 +1227,44 @@ xfce_desktop_connect_settings(XfceDesktop *desktop)
     xfce_desktop_thaw_updates(desktop);
 }
 
-static void
-xfce_desktop_image_filename_changed(XfconfChannel *channel,
-                                    const gchar *property,
-                                    const GValue *value,
-                                    gpointer user_data)
+static gboolean
+xfce_desktop_get_single_workspace_mode(XfceDesktop *desktop)
 {
-    XfceDesktop *desktop = user_data;
-    gchar *p;
-    const gchar *filename;
-    gint monitor, current_workspace;
-    XfceBackdrop *backdrop;
-
-    TRACE("entering");
-
-    p = strstr(property, "/monitor");
-    if(!p)
-        return;
+    g_return_val_if_fail(XFCE_IS_DESKTOP(desktop), TRUE);
 
-    monitor = atoi(p + 8);
-    if(monitor < 0 || monitor >= xfce_desktop_get_n_monitors(desktop))
-        return;
-
-    current_workspace = desktop->priv->current_workspace;
-
-    if(xfce_workspace_get_xinerama_stretch(desktop->priv->workspaces[current_workspace])
-       && monitor != 0)
-        return;
-
-    backdrop = xfce_workspace_get_backdrop(desktop->priv->workspaces[current_workspace],
-                                           monitor);
-
-    if(!G_VALUE_HOLDS_STRING(value))
-        filename = DEFAULT_BACKDROP;
-    else
-        filename = g_value_get_string(value);
-
-    if(G_LIKELY(filename && *filename))
-        xfce_backdrop_set_image_filename(backdrop, filename);
+    return desktop->priv->single_workspace_mode;
 }
 
 static gint
 xfce_desktop_get_current_workspace(XfceDesktop *desktop)
 {
+    WnckWorkspace *wnck_workspace;
+    gint workspace_num, current_workspace;
+
     g_return_val_if_fail(XFCE_IS_DESKTOP(desktop), -1);
 
-    return desktop->priv->current_workspace;
+    wnck_workspace = wnck_screen_get_active_workspace(desktop->priv->wnck_screen);
+
+    if(wnck_workspace != NULL) {
+        workspace_num = wnck_workspace_get_number(wnck_workspace);
+    } else {
+        workspace_num = desktop->priv->nworkspaces;
+    }
+
+    /* If we're in single_workspace mode we need to return the workspace that
+     * it was set to, if possible, otherwise return the current workspace */
+    if(xfce_desktop_get_single_workspace_mode(desktop) &&
+       desktop->priv->single_workspace_num < desktop->priv->nworkspaces) {
+        current_workspace = desktop->priv->single_workspace_num;
+    } else {
+        current_workspace = workspace_num;
+    }
+
+    DBG("workspace_num %d, single_workspace_num %d, current_workspace %d, max workspaces %d",
+        workspace_num, desktop->priv->single_workspace_num, current_workspace,
+        desktop->priv->nworkspaces);
+
+    return current_workspace;
 }
 
 /* public api */
@@ -1294,6 +1425,42 @@ xfce_desktop_set_use_icon_font_size(XfceDesktop *desktop,
 #endif
 }
 
+static void
+xfce_desktop_set_single_workspace_mode(XfceDesktop *desktop,
+                                       gboolean single_workspace)
+{
+    g_return_if_fail(XFCE_IS_DESKTOP(desktop));
+
+    if(single_workspace == desktop->priv->single_workspace_mode)
+        return;
+
+    desktop->priv->single_workspace_mode = single_workspace;
+
+    DBG("single_workspace_mode now %s", single_workspace ? "TRUE" : "FALSE");
+
+    /* Fake a screen size changed to update the backdrop */
+    screen_size_changed_cb(desktop->priv->gscreen, desktop);
+}
+
+static void
+xfce_desktop_set_single_workspace_number(XfceDesktop *desktop,
+                                         gint workspace_num)
+{
+    g_return_if_fail(XFCE_IS_DESKTOP(desktop));
+
+    if(workspace_num == desktop->priv->single_workspace_num)
+        return;
+
+    DBG("single_workspace_num now %d", workspace_num);
+
+    desktop->priv->single_workspace_num = workspace_num;
+
+    if(xfce_desktop_get_single_workspace_mode(desktop)) {
+        /* Fake a screen size changed to update the backdrop */
+        screen_size_changed_cb(desktop->priv->gscreen, desktop);
+    }
+}
+
 void
 xfce_desktop_set_session_logout_func(XfceDesktop *desktop,
                                      SessionLogoutFunc logout_func)
@@ -1394,33 +1561,22 @@ xfce_desktop_popup_secondary_root_menu(XfceDesktop *desktop,
 void
 xfce_desktop_refresh(XfceDesktop *desktop)
 {
-    gchar buf[256];
-    gint i, max, current_workspace;
+    gint i, current_workspace;
 
     g_return_if_fail(XFCE_IS_DESKTOP(desktop));
 
     if(!gtk_widget_get_realized(GTK_WIDGET(desktop)))
         return;
 
-    current_workspace = desktop->priv->current_workspace;
-
-    /* reload image */
-    if(xfce_workspace_get_xinerama_stretch(desktop->priv->workspaces[current_workspace]))
-        max = 1;
-    else
-        max = xfce_desktop_get_n_monitors(desktop);
-    for(i = 0; i < max; ++i) {
-        GValue val = { 0, };
+    current_workspace = xfce_desktop_get_current_workspace(desktop);
 
-        g_snprintf(buf, sizeof(buf), "%smonitor%d/workspace%d/last-image",
-                   desktop->priv->property_prefix, i, current_workspace);
-        xfconf_channel_get_property(desktop->priv->channel, buf, &val);
+    /* reload backgrounds */
+    for(i = 0; i < xfce_desktop_get_n_monitors(desktop); i++) {
+        XfceBackdrop *backdrop;
 
-        xfce_desktop_image_filename_changed(desktop->priv->channel, buf,
-                                            &val, desktop);
+        backdrop = xfce_workspace_get_backdrop(desktop->priv->workspaces[current_workspace], i);
 
-        if(G_VALUE_TYPE(&val))
-            g_value_unset(&val);
+        backdrop_changed_cb(backdrop, desktop);
     }
 
 #ifdef ENABLE_DESKTOP_ICONS
diff --git a/src/xfce-workspace.c b/src/xfce-workspace.c
index ba9f327..d6368ea 100644
--- a/src/xfce-workspace.c
+++ b/src/xfce-workspace.c
@@ -82,7 +82,11 @@ struct _XfceWorkspacePriv
 
     guint workspace_num;
     guint nbackdrops;
+    gboolean xinerama_stretch;
     XfceBackdrop **backdrops;
+
+    gulong *first_color_id;
+    gulong *second_color_id;
 };
 
 enum
@@ -106,6 +110,11 @@ static void xfce_workspace_get_property(GObject *object,
 static void xfce_workspace_connect_backdrop_settings(XfceWorkspace *workspace,
                                                    XfceBackdrop *backdrop,
                                                    guint monitor);
+static void xfce_workspace_disconnect_backdrop_settings(XfceWorkspace *workspace,
+                                                        XfceBackdrop *backdrop,
+                                                        guint monitor);
+
+static void xfce_workspace_remove_backdrops(XfceWorkspace *workspace);
 
 G_DEFINE_TYPE(XfceWorkspace, xfce_workspace, G_TYPE_OBJECT)
 
@@ -148,14 +157,34 @@ backdrop_cycle_cb(XfceBackdrop *backdrop, gpointer user_data)
     if(g_strcmp0(backdrop_file, new_backdrop) != 0) {
         xfce_backdrop_set_image_filename(backdrop, new_backdrop);
         g_free(new_backdrop);
-        g_signal_emit(G_OBJECT(user_data), signals[WORKSPACE_BACKDROP_CHANGED], 0, backdrop);
     }
 }
 
 static void
 backdrop_changed_cb(XfceBackdrop *backdrop, gpointer user_data)
 {
+    XfceWorkspace *workspace = XFCE_WORKSPACE(user_data);
     TRACE("entering");
+
+    /* if we were spanning all the screens and we're not doing it anymore
+     * we need to update all the backdrops for this workspace */
+    if(workspace->priv->xinerama_stretch == TRUE &&
+       xfce_workspace_get_xinerama_stretch(workspace) == FALSE) {
+        guint i;
+
+        for(i = 0; i < workspace->priv->nbackdrops; ++i) {
+            /* skip the current backdrop, we'll get it last */
+            if(workspace->priv->backdrops[i] != backdrop) {
+                g_signal_emit(G_OBJECT(user_data),
+                              signals[WORKSPACE_BACKDROP_CHANGED],
+                              0,
+                              workspace->priv->backdrops[i]);
+            }
+        }
+    }
+
+    workspace->priv->xinerama_stretch = xfce_workspace_get_xinerama_stretch(workspace);
+
     /* Propagate it up */
     g_signal_emit(G_OBJECT(user_data), signals[WORKSPACE_BACKDROP_CHANGED], 0, backdrop);
 }
@@ -165,72 +194,52 @@ xfce_workspace_monitors_changed(XfceWorkspace *workspace,
                                 GdkScreen *gscreen)
 {
     guint i;
+    guint n_monitors;
+    GdkVisual *vis = NULL;
 
     TRACE("entering");
 
-    if(workspace->priv->nbackdrops > 1
-       && xfce_workspace_get_xinerama_stretch(workspace)) {
-        /* for xinerama stretch we only need one backdrop */
-        if(workspace->priv->nbackdrops > 1) {
-            for(i = 1; i < workspace->priv->nbackdrops; ++i)
-                g_object_unref(G_OBJECT(workspace->priv->backdrops[i]));
-        }
+    vis = gdk_screen_get_rgba_visual(gscreen);
+    if(vis == NULL)
+        vis = gdk_screen_get_system_visual(gscreen);
 
-        if(workspace->priv->nbackdrops != 1) {
-            workspace->priv->backdrops = g_realloc(workspace->priv->backdrops,
-                                                 sizeof(XfceBackdrop *));
-            if(!workspace->priv->nbackdrops) {
-                GdkVisual *vis = gdk_screen_get_rgba_visual(gscreen);
-                if(vis == NULL)
-                    vis = gdk_screen_get_system_visual(gscreen);
-
-                workspace->priv->backdrops[0] = xfce_backdrop_new(vis);
-                xfce_workspace_connect_backdrop_settings(workspace,
-                                                       workspace->priv->backdrops[0],
-                                                       0);
-                g_signal_connect(G_OBJECT(workspace->priv->backdrops[0]),
-                                 "changed",
-                                 G_CALLBACK(backdrop_changed_cb), workspace);
-                g_signal_connect(G_OBJECT(workspace->priv->backdrops[0]),
-                                 "cycle",
-                                 G_CALLBACK(backdrop_cycle_cb), workspace);
-            }
-            workspace->priv->nbackdrops = 1;
-        }
+    if(workspace->priv->nbackdrops > 0 &&
+       xfce_workspace_get_xinerama_stretch(workspace)) {
+        /* When spanning screens we only need one backdrop */
+        n_monitors = 1;
     } else {
-        /* We need one backdrop per monitor */
-        guint n_monitors = gdk_screen_get_n_monitors(gscreen);
-
-        if(n_monitors < workspace->priv->nbackdrops) {
-            for(i = n_monitors; i < workspace->priv->nbackdrops; ++i)
-                g_object_unref(G_OBJECT(workspace->priv->backdrops[i]));
-        }
+        n_monitors = gdk_screen_get_n_monitors(gscreen);
+    }
 
-        if(n_monitors != workspace->priv->nbackdrops) {
-            workspace->priv->backdrops = g_realloc(workspace->priv->backdrops,
-                                                 sizeof(XfceBackdrop *) * n_monitors);
-            if(n_monitors > workspace->priv->nbackdrops) {
-                GdkVisual *vis = gdk_screen_get_rgba_visual(gscreen);
-                if(vis == NULL)
-                    vis = gdk_screen_get_system_visual(gscreen);
-
-                for(i = workspace->priv->nbackdrops; i < n_monitors; ++i) {
-                    workspace->priv->backdrops[i] = xfce_backdrop_new(vis);
-                    xfce_workspace_connect_backdrop_settings(workspace,
-                                                           workspace->priv->backdrops[i],
-                                                           i);
-                    g_signal_connect(G_OBJECT(workspace->priv->backdrops[0]),
-                                     "changed",
-                                     G_CALLBACK(backdrop_changed_cb), workspace);
-                    g_signal_connect(G_OBJECT(workspace->priv->backdrops[i]),
-                                     "cycle",
-                                     G_CALLBACK(backdrop_cycle_cb),
-                                     workspace);
-                }
-            }
-            workspace->priv->nbackdrops = n_monitors;
-        }
+    /* Remove all backdrops so that the correct monitor is added/removed and
+     * things stay in the correct order */
+    xfce_workspace_remove_backdrops(workspace);
+
+    /* Allocate space for the backdrops and their color properties so they
+     * can correctly be removed */
+    workspace->priv->backdrops = g_realloc(workspace->priv->backdrops,
+                                           sizeof(XfceBackdrop *) * n_monitors);
+    workspace->priv->first_color_id = g_realloc(workspace->priv->first_color_id,
+                                                sizeof(gulong) * n_monitors);
+    workspace->priv->second_color_id = g_realloc(workspace->priv->second_color_id,
+                                                 sizeof(gulong) * n_monitors);
+
+    for(i = 0; i < n_monitors; ++i) {
+        DBG("Adding workspace %d backdrop %d", workspace->priv->workspace_num, i);
+
+        workspace->priv->backdrops[i] = xfce_backdrop_new(vis);
+        xfce_workspace_connect_backdrop_settings(workspace,
+                                               workspace->priv->backdrops[i],
+                                               i);
+        g_signal_connect(G_OBJECT(workspace->priv->backdrops[i]),
+                         "changed",
+                         G_CALLBACK(backdrop_changed_cb), workspace);
+        g_signal_connect(G_OBJECT(workspace->priv->backdrops[i]),
+                         "cycle",
+                         G_CALLBACK(backdrop_cycle_cb),
+                         workspace);
     }
+    workspace->priv->nbackdrops = n_monitors;
 }
 
 static void
@@ -267,9 +276,13 @@ xfce_workspace_finalize(GObject *object)
 {
     XfceWorkspace *workspace = XFCE_WORKSPACE(object);
 
+    xfce_workspace_remove_backdrops(workspace);
+
     g_object_unref(G_OBJECT(workspace->priv->channel));
     g_free(workspace->priv->property_prefix);
-
+    g_free(workspace->priv->backdrops);
+    g_free(workspace->priv->first_color_id);
+    g_free(workspace->priv->second_color_id);
 }
 
 static void
@@ -321,19 +334,21 @@ xfce_workspace_connect_backdrop_settings(XfceWorkspace *workspace,
     }
     pp_len = strlen(buf);
 
+    DBG("prefix string: %s", buf);
+
     g_strlcat(buf, "color-style", sizeof(buf));
     xfconf_g_property_bind(channel, buf, XFCE_TYPE_BACKDROP_COLOR_STYLE,
                            G_OBJECT(backdrop), "color-style");
 
     buf[pp_len] = 0;
     g_strlcat(buf, "color1", sizeof(buf));
-    xfconf_g_property_bind_gdkcolor(channel, buf,
-                                    G_OBJECT(backdrop), "first-color");
+    workspace->priv->first_color_id[monitor] = xfconf_g_property_bind_gdkcolor(channel, buf,
+                                                            G_OBJECT(backdrop), "first-color");
 
     buf[pp_len] = 0;
     g_strlcat(buf, "color2", sizeof(buf));
-    xfconf_g_property_bind_gdkcolor(channel, buf,
-                                    G_OBJECT(backdrop), "second-color");
+    workspace->priv->second_color_id[monitor] = xfconf_g_property_bind_gdkcolor(channel, buf,
+                                                            G_OBJECT(backdrop), "second-color");
 
     buf[pp_len] = 0;
     g_strlcat(buf, "image-style", sizeof(buf));
@@ -341,11 +356,6 @@ xfce_workspace_connect_backdrop_settings(XfceWorkspace *workspace,
                            G_OBJECT(backdrop), "image-style");
 
     buf[pp_len] = 0;
-    g_strlcat(buf, "brightness", sizeof(buf));
-    xfconf_g_property_bind(channel, buf, G_TYPE_INT,
-                           G_OBJECT(backdrop), "brightness");
-
-    buf[pp_len] = 0;
     g_strlcat(buf, "backdrop-cycle-enable", sizeof(buf));
     xfconf_g_property_bind(channel, buf, G_TYPE_BOOLEAN,
                            G_OBJECT(backdrop), "backdrop-cycle-enable");
@@ -368,7 +378,37 @@ xfce_workspace_connect_backdrop_settings(XfceWorkspace *workspace,
     g_free(monitor_name);
 }
 
+static void
+xfce_workspace_disconnect_backdrop_settings(XfceWorkspace *workspace,
+                                            XfceBackdrop *backdrop,
+                                            guint monitor)
+{
+    TRACE("entering");
+
+    g_return_if_fail(XFCE_IS_BACKDROP(backdrop));
+
+    xfconf_g_property_unbind_all(G_OBJECT(backdrop));
+}
 
+static void
+xfce_workspace_remove_backdrops(XfceWorkspace *workspace)
+{
+    guint i;
+    guint n_monitors;
+
+    g_return_if_fail(XFCE_IS_WORKSPACE(workspace));
+
+    n_monitors = gdk_screen_get_n_monitors(workspace->priv->gscreen);
+
+    for(i = 0; i < n_monitors && i < workspace->priv->nbackdrops; ++i) {
+        xfce_workspace_disconnect_backdrop_settings(workspace,
+                                                    workspace->priv->backdrops[i],
+                                                    i);
+        g_object_unref(G_OBJECT(workspace->priv->backdrops[i]));
+        workspace->priv->backdrops[i] = NULL;
+    }
+    workspace->priv->nbackdrops = 0;
+}
 
 /* public api */
 
diff --git a/src/xfdesktop-file-icon-manager.c b/src/xfdesktop-file-icon-manager.c
index d68ff73..8f4d72a 100644
--- a/src/xfdesktop-file-icon-manager.c
+++ b/src/xfdesktop-file-icon-manager.c
@@ -1202,122 +1202,6 @@ xfdesktop_file_icon_menu_fill_template_menu(GtkWidget *menu,
   g_list_free(files);
 
   return have_templates;
-#if 0
-  dp = g_dir_open (absolute_path, 0, NULL);
-  g_free (absolute_path);
-
-  /* read the directory contents (if opened successfully) */
-  if (G_LIKELY (dp != NULL))
-    {
-      /* process all files within the directory */
-      for (;;)
-        {
-          /* read the name of the next file */
-          name = g_dir_read_name (dp);
-          if (G_UNLIKELY (name == NULL))
-            break;
-          else if (name[0] == '.')
-            continue;
-
-          /* determine the info for that file */
-          path = thunar_vfs_path_relative (templates_path, name);
-          info = thunar_vfs_info_new_for_path (path, NULL);
-          thunar_vfs_path_unref (path);
-
-          /* add the info (if any) to our list */
-          if (G_LIKELY (info != NULL))
-            info_list = g_list_insert_sorted (info_list, info, info_compare);
-        }
-
-      /* close the directory handle */
-      g_dir_close (dp);
-    }
-
-  /* check if we have any infos */
-  if (G_UNLIKELY (info_list == NULL))
-    return FALSE;
-
-  /* determine the icon theme for the menu */
-  icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (menu));
-
-  /* add menu items for all infos */
-  for (lp = info_list; lp != NULL; lp = lp->next)
-    {
-      /* determine the info */
-      info = lp->data;
-
-      /* check if we have a regular file or a directory here */
-      if (G_LIKELY (info->type == THUNAR_VFS_FILE_TYPE_REGULAR))
-        {
-          /* generate a label by stripping off the extension */
-          label = g_strdup (info->display_name);
-          dot = g_utf8_strrchr (label, -1, '.');
-          if (G_LIKELY (dot != NULL))
-            *dot = '\0';
-
-          /* allocate a new menu item */
-          item = gtk_image_menu_item_new_with_label (label);
-          g_object_set_data_full (G_OBJECT (item), I_("thunar-vfs-info"), thunar_vfs_info_ref (info), (GDestroyNotify) thunar_vfs_info_unref);
-          g_signal_connect (G_OBJECT (item), "activate",
-                            G_CALLBACK (xfdesktop_file_icon_template_item_activated),
-                            fmanager);
-          gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
-          gtk_widget_show (item);
-
-          /* lookup the icon for the mime type of that file */
-          icon_name = thunar_vfs_mime_info_lookup_icon_name (info->mime_info, icon_theme);
-
-          /* generate an image based on the named icon */
-          image = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_MENU);
-          gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
-          gtk_widget_show (image);
-
-          /* cleanup */
-          g_free (label);
-          
-          have_templates = TRUE;
-        }
-      else if (info->type == THUNAR_VFS_FILE_TYPE_DIRECTORY)
-        {
-          /* allocate a new submenu for the directory */
-          submenu = gtk_menu_new ();
-          g_object_ref_sink (G_OBJECT (submenu));
-          gtk_menu_set_screen (GTK_MENU (submenu), gtk_widget_get_screen (menu));
-
-          /* fill the submenu from the folder contents */
-          have_templates = xfdesktop_file_icon_menu_fill_template_menu(submenu,
-                                                                       info->path,
-                                                                       fmanager)
-                           || have_templates;
-
-          /* check if any items were added to the submenu */
-          if (G_LIKELY (GTK_MENU_SHELL (submenu)->children != NULL))
-            {
-              /* hook up the submenu */
-              item = gtk_image_menu_item_new_with_label (info->display_name);
-              gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), submenu);
-              gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
-              gtk_widget_show (item);
-
-              /* lookup the icon for the mime type of that file */
-              icon_name = thunar_vfs_mime_info_lookup_icon_name (info->mime_info, icon_theme);
-
-              /* generate an image based on the named icon */
-              image = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_MENU);
-              gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
-              gtk_widget_show (image);
-            }
-
-          /* cleanup */
-          g_object_unref (G_OBJECT (submenu));
-        }
-    }
-
-  /* release the info list */
-  thunar_vfs_info_list_free (info_list);
-#endif
-  
-  return have_templates;
 }
 
 #ifdef HAVE_THUNARX


More information about the Xfce4-commits mailing list