[Xfce4-commits] <xfdesktop:master> xfdesktop supports per-workspace wallpapers (Bug #369)

Eric Koegel noreply at xfce.org
Sat Jan 26 05:30:01 CET 2013


Updating branch refs/heads/master
         to 88a920697b22b0653f244ede15f8e645ae013139 (commit)
       from 5ce0575f81d4fb086978b8068aca34bebbc55edf (commit)

commit 88a920697b22b0653f244ede15f8e645ae013139
Author: Eric Koegel <eric.koegel at gmail.com>
Date:   Sat Jan 26 07:16:42 2013 +0300

    xfdesktop supports per-workspace wallpapers (Bug #369)
    
    Additionally xfdesktop-settings includes quite a few of the layout
    changes from the Xfce Design SIG (i.e. on the background tab the
    images are displayed in an iconview, the settings window changes
    depening on which monitor/workspace it is on, etc).

 common/xfdesktop-common.c                          |  230 +---
 common/xfdesktop-common.h                          |   12 +-
 settings/Makefile.am                               |    3 +
 settings/main.c                                    | 1354 ++++++--------------
 .../xfdesktop-settings-appearance-frame-ui.glade   |  455 +------
 settings/xfdesktop-settings-ui.glade               |  111 +--
 src/Makefile.am                                    |    2 +
 src/xfce-backdrop.c                                |  182 +--
 src/xfce-backdrop.h                                |   19 +-
 src/xfce-desktop.c                                 |  493 +++----
 src/xfce-desktop.h                                 |    8 +-
 src/xfce-workspace.c                               |  432 +++++++
 src/xfce-workspace.h                               |   78 ++
 13 files changed, 1314 insertions(+), 2065 deletions(-)

diff --git a/common/xfdesktop-common.c b/common/xfdesktop-common.c
index 34942a5..344611a 100644
--- a/common/xfdesktop-common.c
+++ b/common/xfdesktop-common.c
@@ -56,156 +56,96 @@
 #define O_BINARY  0
 #endif
 
-gboolean
-xfdesktop_backdrop_list_is_valid(const gchar *path)
+static GList *
+list_files_in_dir(const gchar *path)
 {
-    FILE *fp;
-    gchar buf[512];
-    gint size;
-    gboolean is_list = FALSE;
+    GDir *dir;
+    gboolean needs_slash = TRUE;
+    const gchar *file;
+    GList *files = NULL;
+
+    dir = g_dir_open(path, 0, 0);
+    if(!dir)
+        return NULL;
 
-    size = sizeof(LIST_TEXT);
+    if(path[strlen(path)-1] == '/')
+        needs_slash = FALSE;
 
-    if(!(fp = fopen (path, "r")))
-        return FALSE;
+    while((file = g_dir_read_name(dir))) {
+        gchar *current_file = g_strdup_printf(needs_slash ? "%s/%s" : "%s%s",
+                                              path, file);
+
+        files = g_list_insert_sorted(files, current_file, (GCompareFunc)g_strcmp0);
+    }
 
-    if(fgets(buf, size, fp) && !strncmp(LIST_TEXT, buf, size - 1))
-        is_list = TRUE;
-    fclose(fp);
+    g_dir_close(dir);
 
-    return is_list;
+    return files;
 }
 
-gchar **
-xfdesktop_backdrop_list_load(const gchar *filename,
-                             gint *n_items,
-                             GError **error)
+
+gchar *
+xfdesktop_backdrop_choose_next(const gchar *filename)
 {
-    gchar *contents = NULL, **files = NULL, *p, *q;
-    gsize length = 0;
-    gint arr_size = 10, count = 0;
+    GList *files, *current_file, *start_file;
+    gchar *file = NULL;
 
-    g_return_val_if_fail(filename && (!error || !*error), NULL);
+    g_return_val_if_fail(filename, NULL);
 
-    if(!g_file_get_contents(filename, &contents, &length, error))
+    files = list_files_in_dir(g_path_get_dirname(filename));
+    if(!files)
         return NULL;
 
-    if(strncmp(LIST_TEXT, contents, sizeof(LIST_TEXT) - 1)) {
-        if(error) {
-            g_set_error(error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
-                        _("Backdrop list file is not valid"));
-        }
-        g_free(contents);
-        return NULL;
-    }
+    /* Get the our current background in the list */
+    current_file = g_list_find_custom(files, filename, (GCompareFunc)g_strcmp0);
 
-    /* i'd use g_strsplit() here, but then counting is slower.  we can
-     * also filter out blank lines */
-    files = g_malloc(sizeof(gchar *) * (arr_size+1));
-    p = contents + sizeof(LIST_TEXT);
-    while(p && *p) {
-        q = strstr(p, "\n");
-        if(q) {
-            if(p == q)  /* blank line */
-                continue;
-            *q = 0;
-        } else
-            q = contents + length;  /* assume no trailing '\n' at EOF */
-
-        if(count == arr_size) {
-            arr_size += 10;
-            files = g_realloc(files, sizeof(gchar *) * (arr_size+1));
-        }
+    /* if somehow we don't have a valid file, grab the first one available */
+    if(current_file == NULL)
+        current_file = g_list_first(files);
 
-        files[count++] = g_strdup(p);
-        if(q != contents + length)
-            p = q + 1;
-    }
-    files[count] = NULL;
-    files = g_realloc(files, sizeof(gchar *) * (count+1));
+    start_file = current_file;
 
-    if(n_items)
-        *n_items = count;
+    /* We want the next valid image file in the dir while making sure
+     * we don't loop on ourselves */
+    do {
+        current_file = g_list_next(current_file);
 
-    g_free(contents);
+        /* we hit the end of the list */
+        if(current_file == NULL)
+            current_file = g_list_first(files);
 
-    return files;
-}
+        /* We went through every item in the list */
+        if(g_strcmp0(start_file->data, current_file->data) == 0)
+            break;
 
-gboolean
-xfdesktop_backdrop_list_save(const gchar *filename,
-                             gchar * const *files,
-                             GError **error)
-{
-    gboolean ret = FALSE;
-    gchar *filename_new;
-    FILE *fp;
-    gint i;
-
-    g_return_val_if_fail(filename && (!error || !*error), FALSE);
-
-    filename_new = g_strconcat(filename, ".new", NULL);
-    fp = fopen(filename_new, "w");
-    if(fp) {
-        fprintf(fp, "%s\n", LIST_TEXT);
-        if(files) {
-            for(i = 0; files[i]; ++i)
-                fprintf(fp, "%s\n", files[i]);
-        }
-        if(!fclose(fp)) {
-            if(!rename(filename_new, filename))
-                ret = TRUE;
-            else  {
-                if(error) {
-                    g_set_error(error, G_FILE_ERROR,
-                                g_file_error_from_errno(errno),
-                                "%s", g_strerror(errno));
-                }
-                unlink(filename_new);
-            }
-        } else {
-            if(error) {
-                g_set_error(error, G_FILE_ERROR, g_file_error_from_errno(errno),
-                            "%s", g_strerror(errno));
-            }
-            unlink(filename_new);
-        }
-    } else if(error) {
-        g_set_error(error, G_FILE_ERROR, g_file_error_from_errno(errno),
-                    "%s", g_strerror(errno));
-    }
+    } while(!xfdesktop_image_file_is_valid(current_file->data));
 
-    g_free(filename_new);
+    file = g_strdup(current_file->data);
+    g_list_free_full(files, g_free);
 
-    return ret;
+    return file;
 }
 
 gchar *
-xfdesktop_backdrop_list_choose_random(const gchar *filename,
-                                      GError **error)
+xfdesktop_backdrop_choose_random(const gchar *filename)
 {
     static gboolean __initialized = FALSE;
     static gint previndex = -1;
-    gchar **files, *file = NULL;
-    gint n_items = 0, cur_file, i, tries = 0;
+    GList *files;
+    gchar *file = NULL;
+    gint n_items = 0, cur_file, tries = 0;
 
-    g_return_val_if_fail(filename && (!error || !*error), NULL);
+    g_return_val_if_fail(filename, NULL);
 
-    files = xfdesktop_backdrop_list_load(filename, &n_items, error);
+    files = list_files_in_dir(g_path_get_dirname(filename));
     if(!files)
         return NULL;
-    if(!n_items) {
-        if(error) {
-            g_set_error(error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
-                        _("Backdrop list file is not valid"));
-        }
-        g_strfreev(files);
-        return NULL;
-    }
+
+    n_items = g_list_length(files);
 
     if(1 == n_items) {
-        file = g_strdup(files[0]);
-        g_strfreev(files);
+        file = g_strdup(g_list_first(files)->data);
+        g_list_free_full(files, g_free);
         return file;
     }
 
@@ -226,7 +166,7 @@ xfdesktop_backdrop_list_choose_random(const gchar *filename,
             /* this isn't precise, but if we've failed to get a good
              * image after all this time, let's just give up */
             g_warning("Unable to find good image from list; giving up");
-            g_strfreev(files);
+            g_list_free_full(files, g_free);
             return NULL;
         }
 
@@ -238,65 +178,23 @@ xfdesktop_backdrop_list_choose_random(const gchar *filename,
 #endif
         } while(cur_file == previndex && G_LIKELY(previndex != -1));
 
-    } while(!xfdesktop_image_file_is_valid(files[cur_file]));
+    } while(!xfdesktop_image_file_is_valid(g_list_nth(files, cur_file)->data));
 
     previndex = cur_file;
-    file = files[cur_file];
 
-    /* don't use strfreev() and avoid an extra alloc */
-    for(i = 0; files[i]; ++i) {
-        if(i != cur_file)
-            g_free(files[i]);
-    }
-    g_free(files);
+    file = g_strdup(g_list_nth(files, cur_file)->data);
+    g_list_free_full(files, g_free);
 
     return file;
 }
 
-static void
-pixbuf_loader_size_cb(GdkPixbufLoader *loader, gint width, gint height,
-        gpointer user_data)
-{
-    gboolean *size_read = user_data;
-
-    if(width > 0 && height > 0)
-        *size_read = TRUE;
-}
-
 gboolean
 xfdesktop_image_file_is_valid(const gchar *filename)
 {
-    GdkPixbufLoader *loader;
-    int fd;
-    gboolean size_read = FALSE;
-    guchar buf[4096];
-    gssize len;
-
     g_return_val_if_fail(filename, FALSE);
 
-    fd = open(filename, O_RDONLY|O_BINARY);
-    if(fd < 0)
-        return FALSE;
-
-    loader = gdk_pixbuf_loader_new();
-    g_signal_connect(G_OBJECT(loader), "size-prepared",
-            G_CALLBACK(pixbuf_loader_size_cb), &size_read);
-
-    do {
-        len = read(fd, buf, sizeof(buf));
-        if(len > 0) {
-            if(!gdk_pixbuf_loader_write(loader, buf, len, NULL))
-                break;
-            if(size_read)
-                break;
-        }
-    } while(len > 0);
-
-    close(fd);
-    gdk_pixbuf_loader_close(loader, NULL);
-    g_object_unref(G_OBJECT(loader));
-
-    return size_read;
+    /* 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);
 }
 
 gboolean
diff --git a/common/xfdesktop-common.h b/common/xfdesktop-common.h
index df767f0..7c7570d 100644
--- a/common/xfdesktop-common.h
+++ b/common/xfdesktop-common.h
@@ -33,7 +33,6 @@
 
 #define XFDESKTOP_CHANNEL        "xfce4-desktop"
 #define DEFAULT_BACKDROP         DATADIR "/backgrounds/xfce/xfce-blue.jpg"
-#define DEFAULT_BACKDROP_LIST    "xfce4/desktop/backdrop.list"
 #define DEFAULT_ICON_FONT_SIZE   12
 #define DEFAULT_ICON_SIZE        32
 #define ITHEME_FLAGS             (GTK_ICON_LOOKUP_USE_BUILTIN \
@@ -72,15 +71,8 @@
 
 G_BEGIN_DECLS
 
-gchar **xfdesktop_backdrop_list_load(const gchar *filename,
-                                     gint *n_items,
-                                     GError **error);
-gboolean xfdesktop_backdrop_list_save(const gchar *filename,
-                                      gchar * const *files,
-                                      GError **error);
-gchar *xfdesktop_backdrop_list_choose_random(const gchar *filename,
-                                             GError **error);
-gboolean xfdesktop_backdrop_list_is_valid(const gchar *filename);
+gchar *xfdesktop_backdrop_choose_next(const gchar *filename);
+gchar *xfdesktop_backdrop_choose_random(const gchar *filename);
 
 gboolean xfdesktop_image_file_is_valid(const gchar *filename);
 
diff --git a/settings/Makefile.am b/settings/Makefile.am
index 09cff59..640dd6a 100644
--- a/settings/Makefile.am
+++ b/settings/Makefile.am
@@ -14,8 +14,10 @@ xfdesktop_settings_CFLAGS =						\
 	$(XFCONF_CFLAGS)							\
 	$(GTHREAD_CFLAGS)							\
 	$(LIBX11_CFLAGS)							\
+	$(LIBWNCK_CFLAGS) 							\
 	-DG_LOG_DOMAIN=\"xfdesktop-settings\"		\
 	-DEXO_API_SUBJECT_TO_CHANGE					\
+	-DWNCK_I_KNOW_THIS_IS_UNSTABLE 				\
 	-DLOCALEDIR=\"$(localedir)\"				\
 	-DDATADIR=\"$(datadir)\"					\
 	-DBINDIR=\"$(bindir)\"
@@ -26,6 +28,7 @@ xfdesktop_settings_LDADD =						\
 	$(LIBXFCE4UI_LIBS)							\
 	$(LIBEXO_LIBS)								\
 	$(GTHREAD_LIBS)								\
+	$(LIBWNCK_LIBS) 							\
 	$(LIBX11_LIBS)
 
 if HAVE_CYGWIN
diff --git a/settings/main.c b/settings/main.c
index 743398d..7efba7e 100644
--- a/settings/main.c
+++ b/settings/main.c
@@ -47,7 +47,7 @@
 #include <libxfce4util/libxfce4util.h>
 #include <xfconf/xfconf.h>
 #include <libxfce4ui/libxfce4ui.h>
-#include <exo/exo.h>
+#include <libwnck/libwnck.h>
 
 #include "xfdesktop-common.h"
 #include "xfdesktop-settings-ui.h"
@@ -55,6 +55,7 @@
 
 #define PREVIEW_HEIGHT  48
 #define MAX_ASPECT_RATIO 3.0f
+#define PREVIEW_WIDTH 128
 
 #define SHOW_DESKTOP_MENU_PROP               "/desktop-menu/show"
 #define DESKTOP_MENU_SHOW_ICONS_PROP         "/desktop-menu/show-icons"
@@ -76,46 +77,34 @@
 #define DESKTOP_ICONS_SHOW_FILESYSTEM        "/desktop-icons/file-icons/show-filesystem"
 #define DESKTOP_ICONS_SHOW_REMOVABLE         "/desktop-icons/file-icons/show-removable"
 
-#define PER_SCREEN_PROP_FORMAT               "/backdrop/screen%d/monitor%d"
 
 typedef struct
 {
     XfconfChannel *channel;
     gint screen;
     gint monitor;
-    gulong show_image:1,
-           image_selector_loaded:1,
-           image_list_loaded:1;
+    gint workspace;
+    gchar *monitor_name;
+    gulong image_list_loaded:1;
 
     GtkWidget *frame_image_list;
-    GtkWidget *image_treeview;
-    GtkWidget *btn_plus;
-    GtkWidget *btn_minus;
-    GtkWidget *btn_newlist;
+    GtkWidget *image_iconview;
+    GtkWidget *btn_folder;
     GtkWidget *image_style_combo;
-
-    GtkWidget *radio_singleimage;
-    GtkWidget *radio_imagelist;
-    GtkWidget *radio_none;
-
     GtkWidget *color_style_combo;
     GtkWidget *color1_btn;
     GtkWidget *color2_btn;
 
-    GtkWidget *brightness_slider;
-    GtkWidget *saturation_slider;
+    gulong color1_btn_id;
+    gulong color2_btn_id;
 
     GtkWidget *backdrop_cycle_spinbox;
     GtkWidget *backdrop_cycle_chkbox;
+    GtkWidget *random_backdrop_order_chkbox;
 
-    GtkWidget *chk_xinerama_stretch;
-} AppearancePanel;
+    GThread *preview_thread;
 
-typedef struct
-{
-    GtkTreeModel *model;
-    GSList *iters;
-} PreviewData;
+} AppearancePanel;
 
 enum
 {
@@ -135,11 +124,6 @@ enum
     N_ICON_COLS,
 };
 
-enum
-{
-    TARGET_TEXT_URI_LIST = 0,
-};
-
 
 /* assumes gdk lock is held on function enter, and should be held
  * on function exit */
@@ -199,27 +183,6 @@ xfdesktop_settings_do_single_preview(GtkTreeModel *model,
 }
 
 static gpointer
-xfdesktop_settings_create_some_previews(gpointer data)
-{
-    PreviewData *pdata = data;
-    GSList *l;
-
-    GDK_THREADS_ENTER ();
-
-    for(l = pdata->iters; l; l = l->next)
-        xfdesktop_settings_do_single_preview(pdata->model, l->data);
-
-    GDK_THREADS_LEAVE ();
-
-    g_object_unref(G_OBJECT(pdata->model));
-    g_slist_foreach(pdata->iters, (GFunc)gtk_tree_iter_free, NULL);
-    g_slist_free(pdata->iters);
-    g_free(pdata);
-
-    return NULL;
-}
-
-static gpointer
 xfdesktop_settings_create_all_previews(gpointer data)
 {
     GtkTreeModel *model = data;
@@ -360,41 +323,32 @@ setup_special_icon_list(GtkBuilder *gxml,
     g_object_unref(G_OBJECT(ls));
 }
 
+
 static gint
-image_list_sort(GtkTreeModel *model,
-                GtkTreeIter *a,
-                GtkTreeIter *b,
-                gpointer user_data)
+image_list_compare(GtkTreeModel *model,
+                   const gchar *a,
+                   GtkTreeIter *b)
 {
-    gchar *key_a = NULL, *key_b = NULL;
+    gchar *key_b = NULL;
     gint ret;
 
-    gtk_tree_model_get(model, a, COL_COLLATE_KEY, &key_a, -1);
-    gtk_tree_model_get(model, b, COL_COLLATE_KEY, &key_b, -1);
+    gtk_tree_model_get(model, b, COL_NAME, &key_b, -1);
 
-    if(G_UNLIKELY(!key_a && !key_b))
-        ret = 0;
-    else if(G_UNLIKELY(!key_a))
-        ret = -1;
-    else if(G_UNLIKELY(!key_b))
-        ret = 1;
-    else
-        ret = strcmp(key_a, key_b);
+    ret = g_strcmp0(a, key_b);
 
-    g_free(key_a);
     g_free(key_b);
 
     return ret;
 }
 
 static GtkTreeIter *
-xfdesktop_settings_image_treeview_add(GtkTreeModel *model,
+xfdesktop_settings_image_iconview_add(GtkTreeModel *model,
                                       const char *path)
 {
-    gboolean added = FALSE;
-    GtkTreeIter iter;
+    gboolean added = FALSE, found = FALSE, valid = FALSE;
+    GtkTreeIter iter, search_iter;
     gchar *name = NULL, *name_utf8 = NULL, *name_markup = NULL;
-    gchar *lower = NULL, *key = NULL;
+    gchar *lower = NULL;
 
     if(!xfdesktop_image_file_is_valid(path))
         return NULL;
@@ -408,13 +362,28 @@ xfdesktop_settings_image_treeview_add(GtkTreeModel *model,
                                                   name_utf8);
 
             lower = g_utf8_strdown(name_utf8, -1);
-            key = g_utf8_collate_key(lower, -1);
 
-            gtk_list_store_append(GTK_LIST_STORE(model), &iter);
+            /* 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) {
+                    found = TRUE;
+                } else {
+                    valid = gtk_tree_model_iter_next(model, &search_iter);
+                }
+            }
+
+            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, key,
+                               COL_COLLATE_KEY, lower,
                                -1);
 
             added = TRUE;
@@ -425,7 +394,6 @@ xfdesktop_settings_image_treeview_add(GtkTreeModel *model,
     g_free(name_utf8);
     g_free(name_markup);
     g_free(lower);
-    g_free(key);
 
     if(added)
         return gtk_tree_iter_copy(&iter);
@@ -455,7 +423,7 @@ xfdesktop_image_list_add_dir(GtkListStore *ls,
         g_snprintf(buf, sizeof(buf), needs_slash ? "%s/%s" : "%s%s",
                    path, file);
 
-        iter = xfdesktop_settings_image_treeview_add(GTK_TREE_MODEL(ls), buf);
+        iter = xfdesktop_settings_image_iconview_add(GTK_TREE_MODEL(ls), buf);
         if(iter) {
             if(cur_image_file && !iter_ret && !strcmp(buf, cur_image_file))
                 iter_ret = iter;
@@ -469,309 +437,100 @@ xfdesktop_image_list_add_dir(GtkListStore *ls,
     return iter_ret;
 }
 
-static gboolean
-xfdesktop_settings_ensure_backdrop_list(gchar *filename,
-                                        GtkWindow *parent)
+static void
+xfdesktop_settings_update_iconview_frame_name(AppearancePanel *panel,
+                                              WnckWorkspace *wnck_workspace)
 {
-    FILE *fp;
-
-    g_return_val_if_fail(filename && *filename, FALSE);
-
-    if(xfdesktop_backdrop_list_is_valid(filename))
-        return TRUE;
+    gchar buf[1024];
+    gchar *workspace_name;
 
-    fp = fopen(filename, "w");
-    if(!fp) {
-        gchar *shortfile = g_path_get_basename(filename);
-        gchar *primary = g_strdup_printf(_("Cannot create backdrop list \"%s\""),
-                                         shortfile);
+    if(panel->monitor < 0 && panel->workspace < 0)
+        return;
 
-        xfce_message_dialog(parent,
-                            _("Backdrop List Error"),
-                            GTK_STOCK_DIALOG_ERROR,
-                            primary, strerror(errno),
-                            GTK_STOCK_CLOSE, GTK_RESPONSE_ACCEPT,
-                            NULL);
-        g_free(primary);
-        g_free(shortfile);
+    workspace_name = g_strdup(wnck_workspace_get_name(wnck_workspace));
 
-        return FALSE;
-    }
+    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);
 
-    fprintf(fp, "%s\n", LIST_TEXT);
-    fclose(fp);
+    gtk_frame_set_label(GTK_FRAME(panel->frame_image_list), buf);
 
-    return TRUE;
+    g_free(workspace_name);
 }
 
-static gchar *
-xfdesktop_settings_dialog_create_load_list(AppearancePanel *panel)
+/* Free the returned string when done using it */
+static gchar*
+xfdesktop_settings_generate_per_workspace_binding_string(AppearancePanel *panel,
+                                                         const gchar* property)
 {
-    gchar *list_file = NULL;
-    GtkWindow *parent = GTK_WINDOW(gtk_widget_get_toplevel(panel->image_treeview));
-    GtkWidget *chooser;
-    gchar *path;
-
-    chooser = gtk_file_chooser_dialog_new(_("Create/Load Backdrop List"),
-                                          parent, GTK_FILE_CHOOSER_ACTION_SAVE,
-                                          GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
-                                          GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
-                                          NULL);
-    path = xfce_resource_save_location(XFCE_RESOURCE_CONFIG,
-                                       "xfce4/desktop/", TRUE);
-    if(path) {
-        gtk_file_chooser_add_shortcut_folder(GTK_FILE_CHOOSER(chooser),
-                                             path, NULL);
-        g_free(path);
-    }
-
-    for(;;) {
-        if(GTK_RESPONSE_ACCEPT != gtk_dialog_run(GTK_DIALOG(chooser))) {
-            gtk_widget_destroy(chooser);
-            return NULL;
-        }
-
-        list_file = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(chooser));
-        if(g_file_test(list_file, G_FILE_TEST_EXISTS)
-           && !xfdesktop_backdrop_list_is_valid(list_file))
-        {
-            gchar *shortfile = g_path_get_basename(list_file);
-            gchar *primary = g_strdup_printf(_("File \"%s\" is not a valid backdrop list file.  Do you wish to overwrite it?"),
-                                             shortfile);
-            gint resp;
-
-            resp = xfce_message_dialog(GTK_WINDOW(chooser),
-                                       _("Invalid List File"),
-                                       GTK_STOCK_DIALOG_ERROR,
-                                       primary,
-                                       _("Overwriting the file will cause its contents to be lost."),
-                                       GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
-                                       XFCE_BUTTON_TYPE_MIXED, GTK_STOCK_SAVE, _("Replace"), GTK_RESPONSE_ACCEPT,
-                                       NULL);
-            g_free(primary);
-            g_free(shortfile);
-
-            if(GTK_RESPONSE_ACCEPT == resp)
-                break;
-            else {
-                g_free(list_file);
-                list_file = NULL;
-            }
-        } else
-            break;
-    }
+    gchar *buf = NULL;
 
-    gtk_widget_destroy(chooser);
-    while(gtk_events_pending())
-        gtk_main_iteration();
-
-    if(!xfdesktop_settings_ensure_backdrop_list(list_file, parent)) {
-        g_free(list_file);
-        return NULL;
+    if(panel->monitor_name == NULL) {
+        buf = g_strdup_printf("/backdrop/screen%d/monitor%d/workspace%d/%s",
+                              panel->screen, panel->monitor, panel->workspace,
+                              property);
+    } else {
+        buf = g_strdup_printf("/backdrop/screen%d/monitor%s/workspace%d/%s",
+                              panel->screen, panel->monitor_name, panel->workspace,
+                              property);
     }
 
-    return list_file;
+    return buf;
 }
 
 static void
-cb_image_selection_changed(GtkTreeSelection *sel,
+cb_image_selection_changed(GtkIconView *icon_view,
                            gpointer user_data)
 {
     AppearancePanel *panel = user_data;
-    GtkTreeModel *model = NULL;
+    GtkTreeModel *model = gtk_icon_view_get_model(icon_view);
     GtkTreeIter iter;
-    gchar *filename = NULL;
-    gchar buf[1024];
+    GList *selected_items = NULL;
+    gchar *filename = NULL, *current_filename = NULL;
+    gchar *buf;
 
     TRACE("entering");
 
-    if(panel->image_list_loaded)
+    if(panel->image_list_loaded && GTK_IS_TREE_MODEL(model))
         return;
 
-    if(!gtk_tree_selection_get_selected(sel, &model, &iter))
-        return;
-
-    gtk_tree_model_get(model, &iter, COL_FILENAME, &filename, -1);
-
-    DBG("got %s, applying to screen %d monitor %d", filename, panel->screen, panel->monitor);
+    selected_items = gtk_icon_view_get_selected_items(icon_view);
 
-    g_snprintf(buf, sizeof(buf), PER_SCREEN_PROP_FORMAT "/image-path",
-               panel->screen, panel->monitor);
-    xfconf_channel_set_string(panel->channel, buf, filename);
-    g_snprintf(buf, sizeof(buf), PER_SCREEN_PROP_FORMAT "/last-single-image",
-               panel->screen, panel->monitor);
-    xfconf_channel_set_string(panel->channel, buf, filename);
-}
-
-static gboolean
-xfdesktop_settings_dialog_populate_image_list(AppearancePanel *panel)
-{
-    gchar prop_image[1024], prop_last[1024], *image_file;
-    GtkListStore *ls;
-    GtkTreeIter *image_file_iter = NULL;
-    gboolean do_sort = TRUE;
-    GtkTreeSelection *sel;
-
-    sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(panel->image_treeview));
-    ls = gtk_list_store_new(N_COLS, GDK_TYPE_PIXBUF, G_TYPE_STRING,
-                            G_TYPE_STRING, G_TYPE_STRING);
-
-    g_snprintf(prop_image, sizeof(prop_image),
-               PER_SCREEN_PROP_FORMAT "/image-path",
-               panel->screen, panel->monitor);
-    image_file = xfconf_channel_get_string(panel->channel, prop_image, NULL);
-
-    if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(panel->radio_imagelist))) {
-        gchar **images;
-
-        g_snprintf(prop_last, sizeof(prop_last),
-                   PER_SCREEN_PROP_FORMAT "/last-image-list",
-                   panel->screen, panel->monitor);
-
-        if(!image_file || !xfdesktop_backdrop_list_is_valid(image_file)) {
-            g_free(image_file);
-            image_file = xfconf_channel_get_string(panel->channel, prop_last,
-                                                   NULL);
-            if(!image_file || !xfdesktop_backdrop_list_is_valid(image_file)) {
-                g_free(image_file);
-                image_file = xfce_resource_save_location(XFCE_RESOURCE_CONFIG,
-                                                         DEFAULT_BACKDROP_LIST,
-                                                         TRUE);
-                if(!xfdesktop_settings_ensure_backdrop_list(image_file,
-                                                            GTK_WINDOW(gtk_widget_get_toplevel(panel->image_treeview))))
-                {
-                    /* FIXME: go back to single image mode or something */
-                    g_free(image_file);
-                    return FALSE;
-                }
-            }
-        }
+    /* We only care about the first selected item because the iconview
+     * should be set to single selection mode */
+    if(!selected_items || g_list_first(selected_items) == NULL)
+        return;
 
-        do_sort = FALSE;
+    if(!gtk_tree_model_get_iter(model, &iter, g_list_first(selected_items)->data))
+        return;
 
-        images = xfdesktop_backdrop_list_load(image_file, NULL, NULL);
-        if(images) {
-            gint i;
+    gtk_tree_model_get(model, &iter, COL_FILENAME, &filename, -1);
 
-            xfconf_channel_set_string(panel->channel, prop_image, image_file);
-            xfconf_channel_set_string(panel->channel, prop_last, image_file);
+    buf = xfdesktop_settings_generate_per_workspace_binding_string(panel, "last-image");
 
-            for(i = 0; images[i]; ++i) {
-                GtkTreeIter *iter = xfdesktop_settings_image_treeview_add(GTK_TREE_MODEL(ls), images[i]);
-                if(iter)
-                    gtk_tree_iter_free(iter);
-            }
+    current_filename = xfconf_channel_get_string(panel->channel, buf, "");
 
-            g_strfreev(images);
-            panel->image_list_loaded = TRUE;
-            panel->image_selector_loaded = FALSE;
-            gtk_tree_selection_set_mode(sel, GTK_SELECTION_MULTIPLE);
-        }
-    } else if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(panel->radio_singleimage))) {
-        GtkTreeIter *tmp;
-        gchar **backdrop_dirs;
-        gint i;
-
-        g_snprintf(prop_last, sizeof(prop_last),
-                   PER_SCREEN_PROP_FORMAT "/last-image",
-                   panel->screen, panel->monitor);
-
-        if(!image_file || !xfdesktop_image_file_is_valid(image_file)) {
-            g_free(image_file);
-            image_file = xfconf_channel_get_string(panel->channel, prop_last,
-                                                   NULL);
-            if(!image_file || !xfdesktop_image_file_is_valid(image_file)) {
-                g_free(image_file);
-                image_file = g_strdup(DEFAULT_BACKDROP);
-            }
-        }
-
-        xfconf_channel_set_string(panel->channel, prop_image, image_file);
-        xfconf_channel_set_string(panel->channel, prop_last, image_file);
-
-        /* Add all backdrops in xfce4/backdrops/ for backwards compatibility with 4.8 */
-        backdrop_dirs = xfce_resource_lookup_all(XFCE_RESOURCE_DATA,
-                                                 "xfce4/backdrops/");
-        for(i = 0; backdrop_dirs[i]; ++i) {
-            tmp = xfdesktop_image_list_add_dir(ls, backdrop_dirs[i],
-                                               image_file);
-            if(tmp)
-                image_file_iter = tmp;
-        }
-        g_strfreev(backdrop_dirs);
-
-        /* Add all backdrops in backgrounds/xfce/ */
-        backdrop_dirs = xfce_resource_lookup_all(XFCE_RESOURCE_DATA,
-                                                 "backgrounds/xfce/");
-        for(i = 0; backdrop_dirs[i]; ++i) {
-            tmp = xfdesktop_image_list_add_dir(ls, backdrop_dirs[i],
-                                               image_file);
-            if(tmp)
-                image_file_iter = tmp;
+    /* check to see if the selection actually did change */
+    if(g_strcmp0(current_filename, filename) != 0) {
+        if(panel->monitor_name == NULL) {
+            DBG("got %s, applying to screen %d monitor %d workspace %d", filename,
+                panel->screen, panel->monitor, panel->workspace);
+        } else {
+            DBG("got %s, applying to screen %d monitor %s workspace %d", filename,
+                panel->screen, panel->monitor_name, panel->workspace);
         }
-        g_strfreev(backdrop_dirs);
-
-        if(!image_file_iter)
-            image_file_iter = xfdesktop_settings_image_treeview_add(GTK_TREE_MODEL(ls), image_file);
 
-        panel->image_list_loaded = FALSE;
-        panel->image_selector_loaded = TRUE;
-        gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
-    } else {
-        g_warning("xfdesktop_settings_populate_image_list() called when image style set to 'none'");
-        return FALSE;
+        xfconf_channel_set_string(panel->channel, buf, filename);
     }
 
-    if(do_sort) {
-        gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(ls), COL_NAME,
-                                        image_list_sort, NULL, NULL);
-        gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(ls), COL_NAME,
-                                             GTK_SORT_ASCENDING);
-    }
-
-    gtk_tree_view_set_model(GTK_TREE_VIEW(panel->image_treeview),
-                            GTK_TREE_MODEL(ls));
-    if(image_file_iter) {
-        gtk_tree_selection_select_iter(sel, image_file_iter);
-        gtk_tree_iter_free(image_file_iter);
-
-        /* remember the tree view to scroll to the selected image in the
-         * thread that creates all the previews */
-        g_object_set_data_full(G_OBJECT(ls), "xfdesktop-tree-view",
-                               g_object_ref(panel->image_treeview),
-                               g_object_unref);
-    }
-
-    /* generate previews of each image -- the new thread will own
-     * the reference on the list store, so let's not unref it here */
-    if(!g_thread_try_new("xfdesktop_settings_create_all_previews",
-                         xfdesktop_settings_create_all_previews, ls, NULL)) {
-        g_critical("Failed to spawn thread; backdrop previews will be unavailable.");
-        g_object_unref(G_OBJECT(ls));
-    }
-
-    g_free(image_file);
-
-    return TRUE;
-}
-
-static void
-newlist_button_clicked(GtkWidget *button,
-                       gpointer user_data)
-{
-    AppearancePanel *panel = user_data;
-    gchar *list_file, propname[1024];
-
-    list_file = xfdesktop_settings_dialog_create_load_list(panel);
-    if(!list_file)
-        return;
-
-    g_snprintf(propname, sizeof(propname), PER_SCREEN_PROP_FORMAT "/image-path",
-               panel->screen, panel->monitor);
-    xfconf_channel_set_string(panel->channel, propname, list_file);
-    g_free(list_file);
-
-    xfdesktop_settings_dialog_populate_image_list(panel);
+    g_list_free(selected_items);
+    g_free(current_filename);
+    g_free(buf);
 }
 
 static void
@@ -779,6 +538,9 @@ cb_xfdesktop_chk_custom_font_size_toggled(GtkCheckButton *button,
                                           gpointer user_data)
 {
     GtkWidget *spin_button = GTK_WIDGET(user_data);
+
+    TRACE("entering");
+
     gtk_widget_set_sensitive(spin_button,
                              gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)));
 }
@@ -788,14 +550,16 @@ cb_xfdesktop_chk_cycle_backdrop_toggled(GtkCheckButton *button,
                                         gpointer user_data)
 {
     gboolean sensitive = FALSE;
-    GtkWidget *spin_button = GTK_WIDGET(user_data);
+    AppearancePanel *panel = user_data;
+
+    TRACE("entering");
 
-    if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)) &&
-       gtk_widget_get_sensitive(GTK_WIDGET(button))) {
+    if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(panel->backdrop_cycle_chkbox))) {
            sensitive = TRUE;
     }
 
-    gtk_widget_set_sensitive(spin_button, sensitive);
+    gtk_widget_set_sensitive(panel->backdrop_cycle_spinbox, sensitive);
+    gtk_widget_set_sensitive(panel->random_backdrop_order_chkbox, sensitive);
 }
 
 static gboolean
@@ -803,6 +567,8 @@ xfdesktop_spin_icon_size_timer(GtkSpinButton *button)
 {
     XfconfChannel *channel = g_object_get_data(G_OBJECT(button), "xfconf-chanel");
 
+    TRACE("entering");
+
     g_return_val_if_fail(XFCONF_IS_CHANNEL(channel), FALSE);
 
     xfconf_channel_set_uint(channel,
@@ -818,6 +584,8 @@ cb_xfdesktop_spin_icon_size_changed(GtkSpinButton *button,
 {
     guint timer_id = 0;
 
+    TRACE("entering");
+
     g_object_set_data(G_OBJECT(button), "xfconf-chanel", user_data);
 
     timer_id = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(button), "timer-id"));
@@ -833,173 +601,62 @@ cb_xfdesktop_spin_icon_size_changed(GtkSpinButton *button,
     g_object_set_data(G_OBJECT(button), "timer-id", GUINT_TO_POINTER(timer_id));
 }
 
-static gboolean
-xfdesktop_settings_save_backdrop_list(AppearancePanel *panel,
-                                      GtkTreeModel *model)
-{
-    gboolean ret = TRUE;
-    gint n_images;
-    gchar **images = NULL, *list_file;
-    GtkTreeIter iter;
-    gchar propname[1024];
-    GError *error = NULL;
-
-    n_images = gtk_tree_model_iter_n_children(model, NULL);
-    images = g_new(gchar *, n_images + 1);
-    images[n_images] = NULL;
-
-    if(gtk_tree_model_get_iter_first(model, &iter)) {
-        gint i = 0;
-
-        do {
-            gtk_tree_model_get(model, &iter,
-                               COL_FILENAME, &(images[i++]),
-                               -1);
-        } while(gtk_tree_model_iter_next(model, &iter));
-    }
-
-    g_snprintf(propname, sizeof(propname),
-               PER_SCREEN_PROP_FORMAT "/last-image-list",
-               panel->screen, panel->monitor);
-    list_file = xfconf_channel_get_string(panel->channel, propname, NULL);
-    if(!list_file) {
-        list_file = xfce_resource_save_location(XFCE_RESOURCE_CONFIG,
-                                                DEFAULT_BACKDROP_LIST, TRUE);
-        g_warning("Didn't find prop %s when saving backdrop list; using default %s",
-                  propname, list_file);
-    }
-
-    if(!xfdesktop_backdrop_list_save(list_file, images, &error)) {
-        gchar *primary = g_strdup_printf(_("Failed to write backdrop list to \"%s\""),
-                                         list_file);
-
-        xfce_message_dialog(GTK_WINDOW(gtk_widget_get_toplevel(panel->frame_image_list)),
-                            _("Backdrop List Error"), GTK_STOCK_DIALOG_ERROR,
-                            primary, error->message,
-                            GTK_STOCK_CLOSE, GTK_RESPONSE_ACCEPT, NULL);
-
-        g_free(primary);
-        g_error_free(error);
-        ret = FALSE;
-    }
-
-    g_free(list_file);
-    g_strfreev(images);
-
-    return ret;
-}
-
 static void
-add_file_button_clicked(GtkWidget *button,
-                        gpointer user_data)
+cb_folder_selection_changed(GtkWidget *button,
+                            gpointer user_data)
 {
     AppearancePanel *panel = user_data;
-    GtkWidget *chooser;
-    GtkFileFilter *filter;
-
-    chooser = gtk_file_chooser_dialog_new(_("Add Image File(s)"),
-                                          GTK_WINDOW(gtk_widget_get_toplevel(button)),
-                                          GTK_FILE_CHOOSER_ACTION_OPEN,
-                                          GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
-                                          GTK_STOCK_ADD, GTK_RESPONSE_ACCEPT,
-                                          NULL);
-    gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(chooser), TRUE);
+    gchar *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(button));
+    GtkListStore *ls;
+    GtkTreeIter *iter;
+    GtkTreePath *path;
+    gchar *last_image, *property;
 
-    filter = gtk_file_filter_new();
-    gtk_file_filter_set_name(filter, _("Image files"));
-    gtk_file_filter_add_pixbuf_formats(filter);
-    gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(chooser), filter);
+    TRACE("entering");
 
-    filter = gtk_file_filter_new();
-    gtk_file_filter_set_name(filter, _("All files"));
-    gtk_file_filter_add_custom(filter, GTK_FILE_FILTER_FILENAME,
-                               (GtkFileFilterFunc)gtk_true, NULL, NULL);
-    gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(chooser), filter);
-
-    exo_gtk_file_chooser_add_thumbnail_preview(GTK_FILE_CHOOSER(chooser));
-
-    if(gtk_dialog_run(GTK_DIALOG(chooser)) == GTK_RESPONSE_ACCEPT) {
-        GSList *filenames = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(chooser));
-        GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(panel->image_treeview));
-        GSList *l;
-        PreviewData *pdata = g_new0(PreviewData, 1);
-        pdata->model = g_object_ref(G_OBJECT(model));
-
-        for(l = filenames; l; l = l->next) {
-            GtkTreeIter *iter = xfdesktop_settings_image_treeview_add(model, l->data);
-            if(iter) {
-                pdata->iters = g_slist_prepend(pdata->iters, iter);
-
-                /* auto-select the first one added */
-                if(l == filenames) {
-                    GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(panel->image_treeview));
-                    gtk_tree_selection_select_iter(sel, iter);
-                }
-            }
-        }
-        g_slist_free(filenames);
+    ls = gtk_list_store_new(N_COLS, GDK_TYPE_PIXBUF, G_TYPE_STRING,
+                            G_TYPE_STRING, G_TYPE_STRING);
 
-        if(!pdata->iters
-           || !g_thread_try_new("xfdesktop_settings_create_some_previews",
-                                xfdesktop_settings_create_some_previews,
-                                pdata, NULL))
-        {
-            if(pdata->iters)
-                g_critical("Unable to create thread for single image preview.");
-            g_object_unref(G_OBJECT(pdata->model));
-            g_slist_foreach(pdata->iters, (GFunc)gtk_tree_iter_free, NULL);
-            g_slist_free(pdata->iters);
-            g_free(pdata);
-        }
+    property = xfdesktop_settings_generate_per_workspace_binding_string(panel, "last-image");
 
-        if(panel->image_list_loaded) {
-            xfdesktop_settings_save_backdrop_list(panel, model);
+    last_image = xfconf_channel_get_string(panel->channel, property, NULL);
 
-            /* if we just added the first image, instruct xfdesktop
-             * to load it */
-            if(gtk_tree_model_iter_n_children(model, NULL) == 1)
-                g_spawn_command_line_async("xfdesktop --reload", NULL);
-        }
-    }
+    if(last_image == NULL)
+        last_image = DEFAULT_BACKDROP;
 
-    gtk_widget_destroy(chooser);
-}
+    iter = xfdesktop_image_list_add_dir(ls, filename, last_image);
 
-static void
-remove_file_button_clicked(GtkWidget *button,
-                           gpointer user_data)
-{
-    AppearancePanel *panel = user_data;
-    GtkTreeSelection *sel;
-    GtkTreeModel *model = NULL;
-    GList *rows, *l;
-
-    sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(panel->image_treeview));
-    rows = gtk_tree_selection_get_selected_rows(sel, &model);
-    if(rows) {
-        GSList *rrefs = NULL, *m;
-        GtkTreeIter iter;
-
-        for(l = rows; l; l = l->next) {
-            rrefs = g_slist_prepend(rrefs, gtk_tree_row_reference_new(model,
-                                                                      l->data));
-            gtk_tree_path_free(l->data);
+    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);
         }
-        g_list_free(rows);
+     }
 
-        for(m = rrefs; m; m = m->next) {
-            GtkTreePath *path = gtk_tree_row_reference_get_path(m->data);
-
-            if(gtk_tree_model_get_iter(model, &iter, path))
-                gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
+    /* 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;
+    }
 
-            gtk_tree_path_free(path);
-            gtk_tree_row_reference_free(m->data);
-        }
-        g_slist_free(rrefs);
+    /* 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);
 
-        xfdesktop_settings_save_backdrop_list(panel, model);
+    if(panel->preview_thread == NULL) {
+        g_critical("Failed to spawn thread; backdrop previews will be unavailable.");
+        g_object_unref(G_OBJECT(ls));
     }
+
+    g_free(property);
 }
 
 static void
@@ -1014,6 +671,8 @@ cb_xfdesktop_combo_color_changed(GtkComboBox *combo,
     };
     AppearancePanel *panel = user_data;
 
+    TRACE("entering");
+
     if(gtk_combo_box_get_active(combo) == COLORS_SOLID) {
         gtk_widget_set_sensitive(panel->color1_btn, TRUE);
         gtk_widget_set_sensitive(panel->color2_btn, FALSE);
@@ -1027,125 +686,114 @@ cb_xfdesktop_combo_color_changed(GtkComboBox *combo,
 }
 
 static void
-cb_image_type_radio_clicked(GtkWidget *w,
-                            gpointer user_data)
+xfdesktop_settings_update_iconview_folder(AppearancePanel *panel)
 {
-    AppearancePanel *panel = user_data;
-    gchar prop_image_show[1024], prop_image_path[1024];
+    gchar *current_folder, *prop_last;
 
-    if(!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)))
-        return;
+    TRACE("entering");
 
-    g_snprintf(prop_image_show, sizeof(prop_image_show),
-               PER_SCREEN_PROP_FORMAT "/image-show", panel->screen,
-               panel->monitor);
-    g_snprintf(prop_image_path, sizeof(prop_image_path),
-               PER_SCREEN_PROP_FORMAT "/image-path", panel->screen,
-               panel->monitor);
-
-    if(w == panel->radio_singleimage) {
-        DBG("widget is singleimage");
-        if(!panel->image_selector_loaded) {
-            DBG("about to populate image list with avail backdrops");
-            if(!xfdesktop_settings_dialog_populate_image_list(panel)) {
-                DBG("show_image=%s", panel->show_image?"true":"false");
-                if(panel->show_image) {
-                    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(panel->radio_imagelist),
-                                                 TRUE);
-                } else {
-                    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(panel->radio_none),
-                                                 TRUE);
-                }
-                return;
-            }
-        }
+    prop_last = xfdesktop_settings_generate_per_workspace_binding_string(panel, "last-image");
 
-        gtk_widget_set_sensitive(panel->btn_minus, FALSE);
-        gtk_widget_set_sensitive(panel->btn_newlist, FALSE);
-        gtk_widget_set_sensitive(panel->frame_image_list, TRUE);
-        gtk_widget_set_sensitive(panel->backdrop_cycle_chkbox, FALSE);
-        gtk_widget_set_sensitive(panel->backdrop_cycle_spinbox, FALSE);
-        DBG("show_image=%s", panel->show_image?"true":"false");
-        if(!panel->show_image) {
-            panel->show_image = TRUE;
-            xfconf_channel_set_bool(panel->channel, prop_image_show, TRUE);
-        }
-    } else if(w == panel->radio_imagelist) {
-        DBG("widget is imagelist");
-        if(!panel->image_list_loaded) {
-            DBG("about to populate image list with backdrop list file");
-            if(!xfdesktop_settings_dialog_populate_image_list(panel)) {
-                DBG("show_image=%s", panel->show_image?"true":"false");
-                if(panel->show_image) {
-                    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(panel->radio_singleimage),
-                                                 TRUE);
-                } else {
-                    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(panel->radio_none),
-                                                 TRUE);
-                }
-                return;
-            }
-        }
+    current_folder = xfconf_channel_get_string(panel->channel, prop_last, NULL);
 
-        gtk_widget_set_sensitive(panel->btn_minus, TRUE);
-        gtk_widget_set_sensitive(panel->btn_newlist, TRUE);
-        gtk_widget_set_sensitive(panel->frame_image_list, TRUE);
-        gtk_widget_set_sensitive(panel->backdrop_cycle_chkbox, TRUE);
-        if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(panel->backdrop_cycle_chkbox)))
-            gtk_widget_set_sensitive(panel->backdrop_cycle_spinbox, TRUE);
-        else
-            gtk_widget_set_sensitive(panel->backdrop_cycle_spinbox, FALSE);
-        DBG("show_image=%s", panel->show_image?"true":"false");
-        if(!panel->show_image) {
-            panel->show_image = TRUE;
-            xfconf_channel_set_bool(panel->channel, prop_image_show, TRUE);
-        }
-    } else if(w == panel->radio_none) {
-        DBG("widget is none");
-        gtk_widget_set_sensitive(panel->frame_image_list, FALSE);
-        gtk_widget_set_sensitive(panel->backdrop_cycle_chkbox, FALSE);
-        gtk_widget_set_sensitive(panel->backdrop_cycle_spinbox, FALSE);
-        DBG("show_image=%s", panel->show_image?"true":"false");
-        if(panel->show_image) {
-            panel->show_image = FALSE;
-            xfconf_channel_set_bool(panel->channel, prop_image_show, FALSE);
-        }
-    }
+    if(current_folder == NULL)
+        current_folder = g_strdup(DEFAULT_BACKDROP);
+
+    gtk_file_chooser_set_current_folder((GtkFileChooser*)panel->btn_folder,
+                                  g_path_get_dirname(current_folder));
+
+    g_free(current_folder);
+    g_free(prop_last);
 }
 
+/* This function is to add or remove all the bindings for the background
+ * tab. It's intended to be used when the app changes monitors or workspaces */
 static void
-cb_show_image_changed(XfconfChannel *channel,
-                      const gchar *property,
-                      const GValue *value,
-                      gpointer user_data)
+xfdesktop_settings_background_tab_change_bindings(AppearancePanel *panel,
+                                                  gboolean remove_binding)
 {
-    AppearancePanel *panel = user_data;
+    gchar *buf;
+    XfconfChannel *channel = panel->channel;
+
+    /* Style combobox */
+    buf = xfdesktop_settings_generate_per_workspace_binding_string(panel, "image-style");
+    if(remove_binding) {
+        xfconf_g_property_unbind_by_property(channel, buf,
+                               G_OBJECT(panel->image_style_combo), "active");
+    } else {
+        xfconf_g_property_bind(channel, buf, G_TYPE_INT,
+                               G_OBJECT(panel->image_style_combo), "active");
+    }
+    g_free(buf);
 
-    TRACE("entering, value=%s, panel->show_image=%s",
-          g_value_get_boolean(value)?"true":"false",
-          panel->show_image?"true":"false");
-    if(g_value_get_boolean(value) == panel->show_image)
-        return;
+    /* Color options*/
+    buf = xfdesktop_settings_generate_per_workspace_binding_string(panel, "color-style");
+    if(remove_binding) {
+        xfconf_g_property_unbind_by_property(channel, buf,
+                           G_OBJECT(panel->color_style_combo), "active");
+    } else {
+        xfconf_g_property_bind(channel, buf, G_TYPE_INT,
+                               G_OBJECT(panel->color_style_combo), "active");
+    }
+    g_free(buf);
+
+    buf = xfdesktop_settings_generate_per_workspace_binding_string(panel, "color1");
+    if(remove_binding) {
+        xfconf_g_property_unbind(panel->color1_btn_id);
+        panel->color1_btn_id = xfconf_g_property_bind_gdkcolor(channel, buf,
+                                                               G_OBJECT(panel->color1_btn),
+                                                               "color");
+    }
+    g_free(buf);
 
-    if(g_value_get_boolean(value)) {
-        gchar propname[1024], *filename;
+    buf = xfdesktop_settings_generate_per_workspace_binding_string(panel, "color2");
+    if(remove_binding) {
+        xfconf_g_property_unbind(panel->color2_btn_id);
+    } else {
+        panel->color2_btn_id = xfconf_g_property_bind_gdkcolor(channel, buf,
+                                                               G_OBJECT(panel->color2_btn),
+                                                               "color");
+    }
+    g_free(buf);
 
-        g_snprintf(propname, sizeof(propname),
-                   PER_SCREEN_PROP_FORMAT "/image-path",
-                   panel->screen, panel->monitor);
-        filename = xfconf_channel_get_string(channel, propname, NULL);
-        if(filename && xfdesktop_backdrop_list_is_valid(filename)) {
-            gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(panel->radio_imagelist),
-                                         TRUE);
-        } else {
-            gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(panel->radio_singleimage),
-                                         TRUE);
-        }
-        g_free(filename);
+    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) {
+        xfconf_g_property_unbind_by_property(channel, buf,
+                           G_OBJECT(panel->backdrop_cycle_chkbox), "active");
     } else {
-        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(panel->radio_none),
-                                     TRUE);
+        xfconf_g_property_bind(channel, buf, G_TYPE_BOOLEAN,
+                               G_OBJECT(panel->backdrop_cycle_chkbox), "active");
     }
+    g_free(buf);
+
+    buf = xfdesktop_settings_generate_per_workspace_binding_string(panel, "backdrop-cycle-timer");
+    if(remove_binding) {
+        xfconf_g_property_unbind_by_property(channel, buf,
+                   G_OBJECT(gtk_spin_button_get_adjustment(GTK_SPIN_BUTTON(panel->backdrop_cycle_spinbox))),
+                   "value");
+    } else {
+        xfconf_g_property_bind(channel, buf, G_TYPE_UINT,
+                       G_OBJECT(gtk_spin_button_get_adjustment(GTK_SPIN_BUTTON(panel->backdrop_cycle_spinbox))),
+                       "value");
+    }
+    g_free(buf);
+
+    buf = xfdesktop_settings_generate_per_workspace_binding_string(panel, "backdrop-cycle-random-order");
+    if(remove_binding) {
+        xfconf_g_property_unbind_by_property(channel, buf,
+                           G_OBJECT(panel->random_backdrop_order_chkbox), "active");
+    } else {
+        xfconf_g_property_bind(channel, buf, G_TYPE_BOOLEAN,
+                               G_OBJECT(panel->random_backdrop_order_chkbox), "active");
+    }
+    g_free(buf);
+
+    cb_xfdesktop_chk_cycle_backdrop_toggled(GTK_CHECK_BUTTON(panel->backdrop_cycle_chkbox),
+                                            panel);
 }
 
 static void
@@ -1157,166 +805,102 @@ suboptions_set_sensitive(GtkToggleButton *btn,
 }
 
 static void
-image_treeview_drag_data_received(GtkWidget *widget,
-                                  GdkDragContext *context,
-                                  gint x,
-                                  gint y,
-                                  GtkSelectionData *selection_data,
-                                  guint info,
-                                  guint time_,
-                                  gpointer user_data)
+cb_update_background_tab(WnckWindow *wnck_window,
+                         gpointer user_data)
 {
     AppearancePanel *panel = user_data;
-    gboolean file_added;
-    gchar *p;
-    GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(widget));
-    PreviewData *pdata = g_new0(PreviewData, 1);
-
-    pdata->model = g_object_ref(G_OBJECT(model));
-
-    if(TARGET_TEXT_URI_LIST != info
-        || gtk_selection_data_get_format(selection_data) != 8
-        || gtk_selection_data_get_length(selection_data) <= 0)
-    {
-        gtk_drag_finish(context, FALSE, FALSE, time_);
-        g_free(pdata);
-        return;
+    gint screen_num, monitor_num, workspace_num;
+    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);
+    screen_num = gdk_screen_get_number(screen);
+    monitor_num = gdk_screen_get_monitor_at_window(screen,
+                                                   gtk_widget_get_window(panel->image_iconview));
+
+    /* Check to see if something changed */
+    if(panel->workspace == workspace_num &&
+       panel->screen == screen_num &&
+       panel->monitor == monitor_num) {
+           return;
     }
 
-    p = (gchar *)gtk_selection_data_get_data(selection_data);
-    while(*p) {
-        if(*p != '#') {
-            gchar *q;
-
-            while(g_ascii_isspace(*p))
-                p++;
-
-            q = p;
-            while(*q && *q != '\n' && *q != '\r')
-                q++;
-
-            if(q > p) {
-                q--;
-                while(g_ascii_isspace(*q))
-                    q--;
-
-                if(!strncmp(p, "file://", 7)) {
-                    /* we only handle file uris */
-                    gchar oldq, *filename;
-
-                    q++;
-                    oldq = *q;
-                    *q = 0;
-
-                    filename = g_filename_from_uri(p, NULL, NULL);
-                    if(filename) {
-                        GtkTreeIter *iter = NULL;
-
-                        if(g_file_test(filename, G_FILE_TEST_IS_DIR)) {
-                            GDir *dir = g_dir_open(filename, 0, 0);
-
-                            if(dir) {
-                                const gchar *name;
-                                gchar buf[PATH_MAX];
-                                gboolean needs_slash = TRUE;
-
-                                if(filename[strlen(filename)-1] == '/')
-                                    needs_slash = FALSE;
-
-                                while((name = g_dir_read_name(dir))) {
-                                    g_snprintf(buf, sizeof(buf),
-                                               needs_slash ? "%s/%s" : "%s%s",
-                                               filename, name);
-                                    iter = xfdesktop_settings_image_treeview_add(model, buf);
-                                    if(iter)
-                                        pdata->iters = g_slist_prepend(pdata->iters, iter);
-                                }
-                                g_dir_close(dir);
-                            }
-                        } else if(g_file_test(filename, G_FILE_TEST_EXISTS)) {
-                            iter = xfdesktop_settings_image_treeview_add(model, filename);
-                            if(iter)
-                                pdata->iters = g_slist_prepend(pdata->iters, iter);
-                        }
-
-                        g_free(filename);
-                    }
-
-                    *q = oldq;
-                }
-            }
-        }
+    TRACE("screen, monitor, or workspace changed");
 
-        p = strchr(p, '\n');
-        if(p)
-            p++;
+    /* remove the old bindings */
+    if(panel->monitor != -1 && panel->workspace != -1) {
+        xfdesktop_settings_background_tab_change_bindings(panel,
+                                                          TRUE);
     }
 
-    file_added = !!pdata->iters;
+    if(panel->monitor_name != NULL)
+        g_free(panel->monitor_name);
 
-    if(!pdata->iters
-       || !g_thread_try_new("xfdesktop_settings_create_some_previews",
-                            xfdesktop_settings_create_some_previews,
-                            pdata, NULL))
-    {
-        if(pdata->iters)
-            g_critical("Unable to create thread for single image preview.");
-        g_object_unref(G_OBJECT(pdata->model));
-        g_slist_foreach(pdata->iters, (GFunc)gtk_tree_iter_free, NULL);
-        g_slist_free(pdata->iters);
-        g_free(pdata);
-    }
+    panel->workspace = workspace_num;
+    panel->screen = screen_num;
+    panel->monitor = monitor_num;
+    panel->monitor_name = gdk_screen_get_monitor_plug_name(screen, panel->monitor);
+
+    /* connect the new bindings */
+    xfdesktop_settings_background_tab_change_bindings(panel,
+                                                      FALSE);
 
-    gtk_drag_finish(context, file_added, FALSE, time_);
+    xfdesktop_settings_update_iconview_frame_name(panel, wnck_workspace);
+    xfdesktop_settings_update_iconview_folder(panel);
 
-    if(file_added && panel->image_list_loaded)
-        xfdesktop_settings_save_backdrop_list(panel, model);
+    /* 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
-xfdesktop_settings_setup_image_treeview(AppearancePanel *panel)
+xfdesktop_settings_setup_image_iconview(AppearancePanel *panel)
 {
-    static GtkTargetEntry drag_targets[] = {
-        { "text/uri-list", 0, TARGET_TEXT_URI_LIST },
-    };
-    GtkCellRenderer *render;
-    GtkTreeViewColumn *col;
-
-    render = gtk_cell_renderer_pixbuf_new();
-    col = gtk_tree_view_column_new_with_attributes("thumbnail", render,
-                                                   "pixbuf", COL_PIX, NULL);
-    gtk_tree_view_append_column(GTK_TREE_VIEW(panel->image_treeview),
-                                col);
-    render = gtk_cell_renderer_text_new();
-    col = gtk_tree_view_column_new_with_attributes("name", render,
-                                                   "markup", COL_NAME, NULL);
-    gtk_tree_view_append_column(GTK_TREE_VIEW(panel->image_treeview),
-                                col);
+    GtkIconView *iconview = GTK_ICON_VIEW(panel->image_iconview);
 
-    g_signal_connect(G_OBJECT(gtk_tree_view_get_selection(GTK_TREE_VIEW(panel->image_treeview))),
-                     "changed",
-                     G_CALLBACK(cb_image_selection_changed), panel);
+    TRACE("entering");
 
-    gtk_tree_view_enable_model_drag_dest(GTK_TREE_VIEW(panel->image_treeview),
-                                         drag_targets, 1,
-                                         GDK_ACTION_DEFAULT | GDK_ACTION_COPY);
+    g_object_set(G_OBJECT(iconview),
+                "pixbuf-column", COL_PIX,
+                "item-width", PREVIEW_WIDTH,
+                NULL);
 
-    g_signal_connect(G_OBJECT(panel->image_treeview), "drag-data-received",
-                     G_CALLBACK(image_treeview_drag_data_received), panel);
+    g_signal_connect(G_OBJECT(iconview), "selection-changed",
+                     G_CALLBACK(cb_image_selection_changed), panel);
 }
 
 static void
-xfdesktop_settings_dialog_add_screens(GtkBuilder *main_gxml,
-                                      XfconfChannel *channel)
+xfdesktop_settings_dialog_setup_tabs(GtkBuilder *main_gxml,
+                                     XfconfChannel *channel,
+                                     GdkScreen *screen)
 {
-    gint i, j, nmonitors, nscreens;
     GtkWidget *appearance_container, *chk_custom_font_size,
-              *spin_font_size, *color_style_widget, *w, *box,
-              *spin_icon_size, *chk_show_thumbnails, *chk_single_click;
+              *spin_font_size, *w, *box, *spin_icon_size,
+              *chk_show_thumbnails, *chk_single_click, *appearance_settings;
+    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"));
 
+    /* Icons tab */
+    /* icon size */
     spin_icon_size = GTK_WIDGET(gtk_builder_get_object(main_gxml, "spin_icon_size"));
 
     g_signal_connect(G_OBJECT(spin_icon_size), "value-changed",
@@ -1328,10 +912,12 @@ xfdesktop_settings_dialog_add_screens(GtkBuilder *main_gxml,
                                                       DESKTOP_ICONS_ICON_SIZE_PROP,
                                                       DEFAULT_ICON_SIZE));
 
+    /* font size */
     chk_custom_font_size = GTK_WIDGET(gtk_builder_get_object(main_gxml,
                                                              "chk_custom_font_size"));
     spin_font_size = GTK_WIDGET(gtk_builder_get_object(main_gxml, "spin_font_size"));
 
+    /* single click */
     chk_single_click = GTK_WIDGET(gtk_builder_get_object(main_gxml,
                                                          "chk_single_click"));
 
@@ -1339,6 +925,7 @@ xfdesktop_settings_dialog_add_screens(GtkBuilder *main_gxml,
                      G_CALLBACK(cb_xfdesktop_chk_custom_font_size_toggled),
                      spin_font_size);
 
+    /* thumbnails */
     chk_show_thumbnails = GTK_WIDGET(gtk_builder_get_object(main_gxml,
                                                             "chk_show_thumbnails"));
     /* The default value when this property is not set, is 'TRUE'.
@@ -1349,230 +936,97 @@ xfdesktop_settings_dialog_add_screens(GtkBuilder *main_gxml,
     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(chk_show_thumbnails),
                                   TRUE);
 
-    nscreens = gdk_display_get_n_screens(gdk_display_get_default());
+    /* Background tab */
+    panel->channel = channel;
+    panel->screen = gdk_screen_get_number(screen);
 
-    for(i = 0; i < nscreens; ++i) {
-        GdkDisplay *gdpy = gdk_display_get_default();
-        GdkScreen *screen = gdk_display_get_screen(gdpy, i);
-        nmonitors = gdk_screen_get_n_monitors(screen);
+    /* 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)));
 
-        if(nscreens > 1 || nmonitors > 1) {
-            gtk_notebook_set_show_tabs(GTK_NOTEBOOK(appearance_container), TRUE);
-            gtk_container_set_border_width(GTK_CONTAINER(appearance_container), 12);
-        }
+    g_signal_connect(wnck_window, "geometry-changed",
+                     G_CALLBACK(cb_update_background_tab), panel);
 
-        for(j = 0; j < nmonitors; ++j) {
-
-            gchar buf[1024];
-            GtkBuilder *appearance_gxml;
-            AppearancePanel *panel = g_new0(AppearancePanel, 1);
-            GtkWidget *appearance_settings, *appearance_label;
-            GError *error = NULL;
-
-            panel->channel = channel;
-            panel->screen = i;
-            panel->monitor = j;
-
-            if(nscreens > 1 && nmonitors > 1) {
-                gchar *monitor_name = gdk_screen_get_monitor_plug_name(screen,
-                                                                       j);
-                if(monitor_name) {
-                    g_snprintf(buf, sizeof(buf),
-                               _("Screen %d, Monitor %d (%s)"), i+1, j+1,
-                               monitor_name);
-                    g_free(monitor_name);
-                } else
-                    g_snprintf(buf, sizeof(buf), _("Screen %d, Monitor %d"),
-                               i+1, j+1);
-            } else if(nscreens > 1)
-                g_snprintf(buf, sizeof(buf), _("Screen %d"), i+1);
-            else {
-                gchar *monitor_name = gdk_screen_get_monitor_plug_name(screen,
-                                                                       j);
-                if(monitor_name) {
-                    g_snprintf(buf, sizeof(buf), _("Monitor %d (%s)"),
-                               j+1, monitor_name);
-                    g_free(monitor_name);
-                } else
-                    g_snprintf(buf, sizeof(buf), _("Monitor %d"), j+1);
-            }
+    /* send invalid numbers so that the update_background_tab will update everything */
+    panel->monitor = -1;
+    panel->workspace = -1;
+    panel->monitor_name = NULL;
 
-            appearance_gxml = gtk_builder_new();
-            if(!gtk_builder_add_from_string(appearance_gxml,
-                                            xfdesktop_settings_appearance_frame_ui,
-                                            xfdesktop_settings_appearance_frame_ui_length,
-                                            &error))
-            {
-                g_printerr("Failed to parse appearance settings UI description: %s\n",
-                           error->message);
-                g_error_free(error);
-                exit(1);
-            }
+    appearance_gxml = gtk_builder_new();
+    if(!gtk_builder_add_from_string(appearance_gxml,
+                                    xfdesktop_settings_appearance_frame_ui,
+                                    xfdesktop_settings_appearance_frame_ui_length,
+                                    &error))
+    {
+        g_printerr("Failed to parse appearance settings UI description: %s\n",
+                   error->message);
+        g_error_free(error);
+        exit(1);
+    }
 
-            appearance_settings = GTK_WIDGET(gtk_builder_get_object(appearance_gxml,
-                                                                    "alignment_settings"));
-
-            appearance_label = gtk_label_new_with_mnemonic(buf);
-            gtk_widget_show(appearance_label);
-
-            gtk_notebook_append_page(GTK_NOTEBOOK(appearance_container),
-                                     appearance_settings, appearance_label);
-
-            /* Connect xfconf bindings */
-            g_snprintf(buf, sizeof(buf), PER_SCREEN_PROP_FORMAT "/brightness",
-                       i, j);
-            panel->brightness_slider = GTK_WIDGET(gtk_builder_get_object(appearance_gxml,
-                                                                         "slider_brightness"));
-            xfconf_g_property_bind(channel, buf, G_TYPE_INT,
-                                   G_OBJECT(gtk_range_get_adjustment(GTK_RANGE(panel->brightness_slider))),
-                                   "value");
-
-            g_snprintf(buf, sizeof(buf), PER_SCREEN_PROP_FORMAT "/saturation",
-                       i, j);
-            panel->saturation_slider = GTK_WIDGET(gtk_builder_get_object(appearance_gxml,
-                                                                         "slider_saturation"));
-            xfconf_g_property_bind(channel, buf, G_TYPE_DOUBLE,
-                                   G_OBJECT(gtk_range_get_adjustment(GTK_RANGE(panel->saturation_slider))),
-                                   "value");
-
-            w = GTK_WIDGET(gtk_builder_get_object(appearance_gxml, "combo_style"));
-            gtk_combo_box_set_active(GTK_COMBO_BOX(w), 0);
-            g_snprintf(buf, sizeof(buf), PER_SCREEN_PROP_FORMAT "/image-style",
-                       i, j);
-            xfconf_g_property_bind(channel, buf, G_TYPE_INT,
-                                   G_OBJECT(w), "active");
-
-            color_style_widget = GTK_WIDGET(gtk_builder_get_object(appearance_gxml,
-                                                                   "combo_colors"));
-            gtk_combo_box_set_active(GTK_COMBO_BOX(color_style_widget), 0);
-            g_snprintf(buf, sizeof(buf), PER_SCREEN_PROP_FORMAT "/color-style",
-                       i, j);
-            xfconf_g_property_bind(channel, buf, G_TYPE_INT,
-                                   G_OBJECT(color_style_widget), "active");
-            g_signal_connect(G_OBJECT(color_style_widget), "changed",
-                             G_CALLBACK(cb_xfdesktop_combo_color_changed),
-                             panel);
-
-            panel->color1_btn = GTK_WIDGET(gtk_builder_get_object(appearance_gxml,
-                                                                  "color1_btn"));
-            g_snprintf(buf, sizeof(buf), PER_SCREEN_PROP_FORMAT "/color1",
-                       i, j);
-            xfconf_g_property_bind_gdkcolor(channel, buf,
-                                            G_OBJECT(panel->color1_btn),
-                                            "color");
-
-            panel->color2_btn = GTK_WIDGET(gtk_builder_get_object(appearance_gxml,
-                                                                  "color2_btn"));
-            g_snprintf(buf, sizeof(buf), PER_SCREEN_PROP_FORMAT "/color2",
-                       i, j);
-            xfconf_g_property_bind_gdkcolor(channel, buf,
-                                            G_OBJECT(panel->color2_btn),
-                                            "color");
-
-            cb_xfdesktop_combo_color_changed(GTK_COMBO_BOX(color_style_widget),
-                                             panel);
-
-            panel->frame_image_list = GTK_WIDGET(gtk_builder_get_object(appearance_gxml,
-                                                                        "frame_image_list"));
-
-            panel->image_treeview = GTK_WIDGET(gtk_builder_get_object(appearance_gxml,
-                                                                      "treeview_imagelist"));
-            xfdesktop_settings_setup_image_treeview(panel);
-
-            panel->btn_plus = GTK_WIDGET(gtk_builder_get_object(appearance_gxml, "btn_plus"));
-            g_signal_connect(G_OBJECT(panel->btn_plus), "clicked",
-                             G_CALLBACK(add_file_button_clicked), panel);
-
-            panel->btn_minus = GTK_WIDGET(gtk_builder_get_object(appearance_gxml,
-                                                                 "btn_minus"));
-            g_signal_connect(G_OBJECT(panel->btn_minus), "clicked",
-                             G_CALLBACK(remove_file_button_clicked), panel);
-
-            panel->btn_newlist = GTK_WIDGET(gtk_builder_get_object(appearance_gxml,
-                                                                   "btn_newlist"));
-            g_signal_connect(G_OBJECT(panel->btn_newlist), "clicked",
-                             G_CALLBACK(newlist_button_clicked), panel);
-
-            panel->chk_xinerama_stretch = GTK_WIDGET(gtk_builder_get_object(appearance_gxml,
-                                                                            "chk_xinerama_stretch"));
-
-            /* The first monitor has the option of doing the xinerama-stretch,
-             * but only if there's multiple monitors attached. Make it invisible
-             * in all other cases.
-             */
-            if(j == 0 && nmonitors > 1) {
-                g_snprintf(buf, sizeof(buf), "/backdrop/screen%d/xinerama-stretch",
-                           i);
-                xfconf_g_property_bind(channel, buf, G_TYPE_BOOLEAN,
-                                        G_OBJECT(panel->chk_xinerama_stretch), "active");
-                gtk_widget_set_sensitive(panel->chk_xinerama_stretch, TRUE);
-            } else {
-                gtk_widget_hide(panel->chk_xinerama_stretch);
-            }
+    appearance_settings = GTK_WIDGET(gtk_builder_get_object(appearance_gxml,
+                                                            "alignment_settings"));
 
-            panel->backdrop_cycle_chkbox = GTK_WIDGET(gtk_builder_get_object(appearance_gxml,
-                                                                             "chk_cycle_backdrop"));
-            panel->backdrop_cycle_spinbox = GTK_WIDGET(gtk_builder_get_object(appearance_gxml,
-                                                                             "spin_backdrop_time_minutes"));
+    panel->frame_image_list = GTK_WIDGET(gtk_builder_get_object(appearance_gxml,
+                                                                "frame_image_list"));
 
-            g_signal_connect(G_OBJECT(panel->backdrop_cycle_chkbox), "toggled",
-                            G_CALLBACK(cb_xfdesktop_chk_cycle_backdrop_toggled),
-                            panel->backdrop_cycle_spinbox);
+    gtk_table_attach_defaults(GTK_TABLE(appearance_container),
+                             appearance_settings, 0,1,0,1);
 
-            g_snprintf(buf, sizeof(buf), PER_SCREEN_PROP_FORMAT "/backdrop-cycle-enable",
-                       i, j);
-            xfconf_g_property_bind(channel, buf, G_TYPE_BOOLEAN,
-                                   G_OBJECT(panel->backdrop_cycle_chkbox), "active");
+    panel->image_style_combo = GTK_WIDGET(gtk_builder_get_object(appearance_gxml, "combo_style"));
 
-            g_snprintf(buf, sizeof(buf), PER_SCREEN_PROP_FORMAT "/backdrop-cycle-timer",
-                       i, j);
-            xfconf_g_property_bind(channel, buf, G_TYPE_UINT,
-                           G_OBJECT(gtk_spin_button_get_adjustment(GTK_SPIN_BUTTON(panel->backdrop_cycle_spinbox))),
-                           "value");
+    panel->color_style_combo = GTK_WIDGET(gtk_builder_get_object(appearance_gxml,
+                                                                 "combo_colors"));
 
-            panel->radio_singleimage = GTK_WIDGET(gtk_builder_get_object(appearance_gxml,
-                                                                         "radio_singleimage"));
-            g_signal_connect(G_OBJECT(panel->radio_singleimage), "toggled",
-                             G_CALLBACK(cb_image_type_radio_clicked), panel);
-            panel->radio_imagelist = GTK_WIDGET(gtk_builder_get_object(appearance_gxml,
-                                                                       "radio_imagelist"));
-            g_signal_connect(G_OBJECT(panel->radio_imagelist), "toggled",
-                             G_CALLBACK(cb_image_type_radio_clicked), panel);
-            panel->radio_none = GTK_WIDGET(gtk_builder_get_object(appearance_gxml,
-                                                                  "radio_none"));
-            g_signal_connect(G_OBJECT(panel->radio_none), "toggled",
-                             G_CALLBACK(cb_image_type_radio_clicked), panel);
-            g_snprintf(buf, sizeof(buf),
-                       "property-changed::" PER_SCREEN_PROP_FORMAT "/image-show",
-                       i, j);
-            g_signal_connect(G_OBJECT(channel), buf,
-                             G_CALLBACK(cb_show_image_changed), panel);
-
-            if(!xfconf_channel_get_bool(channel, buf+18, TRUE)) {
-                panel->show_image = FALSE;
-                gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(panel->radio_none),
-                                             TRUE);
-            } else {
-                gchar *image_path = NULL;
+    /* 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);
 
-                panel->show_image = TRUE;
+    g_signal_connect(G_OBJECT(panel->color_style_combo), "changed",
+                     G_CALLBACK(cb_xfdesktop_combo_color_changed),
+                     panel);
 
-                g_snprintf(buf, sizeof(buf),
-                           PER_SCREEN_PROP_FORMAT "/image-path", i, j);
-                image_path = xfconf_channel_get_string(channel, buf, NULL);
-                if(image_path && xfdesktop_backdrop_list_is_valid(image_path)) {
-                    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(panel->radio_imagelist),
-                                                 TRUE);
-                } else
-                    xfdesktop_settings_dialog_populate_image_list(panel);
-                g_free(image_path);
+    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_object_unref(G_OBJECT(appearance_gxml));
-        }
-    }
+    /* icon view area */
+    panel->frame_image_list = GTK_WIDGET(gtk_builder_get_object(appearance_gxml,
+                                                                "frame_image_list"));
+
+    panel->image_iconview = GTK_WIDGET(gtk_builder_get_object(appearance_gxml,
+                                                              "iconview_imagelist"));
+    xfdesktop_settings_setup_image_iconview(panel);
+
+    /* folder: file chooser button */
+    panel->btn_folder = GTK_WIDGET(gtk_builder_get_object(appearance_gxml, "btn_folder"));
+    g_signal_connect(G_OBJECT(panel->btn_folder), "selection-changed",
+                     G_CALLBACK(cb_folder_selection_changed), panel);
+
+    filter = gtk_file_filter_new();
+    gtk_file_filter_set_name(filter, _("Image files"));
+    gtk_file_filter_add_pixbuf_formats(filter);
+    gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(panel->btn_folder), filter);
+
+    /* background cycle timer */
+    panel->backdrop_cycle_chkbox = GTK_WIDGET(gtk_builder_get_object(appearance_gxml,
+                                                                     "chk_cycle_backdrop"));
+    panel->backdrop_cycle_spinbox = GTK_WIDGET(gtk_builder_get_object(appearance_gxml,
+                                                                     "spin_backdrop_time_minutes"));
+    panel->random_backdrop_order_chkbox = GTK_WIDGET(gtk_builder_get_object(appearance_gxml,
+                                                                     "chk_random_backdrop_order"));
 
+    g_signal_connect(G_OBJECT(panel->backdrop_cycle_chkbox), "toggled",
+                    G_CALLBACK(cb_xfdesktop_chk_cycle_backdrop_toggled),
+                    panel);
+
+    g_object_unref(G_OBJECT(appearance_gxml));
+
+
+    /* Menus Tab */
     w = GTK_WIDGET(gtk_builder_get_object(main_gxml, "chk_show_desktop_menu"));
     xfconf_g_property_bind(channel, SHOW_DESKTOP_MENU_PROP, G_TYPE_BOOLEAN,
                            G_OBJECT(w), "active");
@@ -1714,13 +1168,13 @@ main(int argc, char **argv)
 
     channel = xfconf_channel_new(XFDESKTOP_CHANNEL);
 
-    xfdesktop_settings_dialog_add_screens(gxml, channel);
-
     if(opt_socket_id == 0) {
         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));
 
         /* To prevent the settings dialog to be saved in the session */
         gdk_x11_set_sm_client_id("FAKE ID");
@@ -1733,6 +1187,8 @@ 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();
 
diff --git a/settings/xfdesktop-settings-appearance-frame-ui.glade b/settings/xfdesktop-settings-appearance-frame-ui.glade
index a397d94..ebcb407 100644
--- a/settings/xfdesktop-settings-appearance-frame-ui.glade
+++ b/settings/xfdesktop-settings-appearance-frame-ui.glade
@@ -1,22 +1,6 @@
 <?xml version="1.0"?>
 <!--Generated with glade3 3.4.5 on Sun Nov 16 16:39:43 2008 -->
 <interface>
-  <object class="GtkAdjustment" id="adjustment1">
-    <property name="upper">127</property>
-    <property name="lower">-128</property>
-    <property name="page_increment">10</property>
-    <property name="step_increment">1</property>
-    <property name="page_size">0</property>
-    <property name="value">0</property>
-  </object>
-  <object class="GtkAdjustment" id="adjustment2">
-    <property name="upper">10</property>
-    <property name="lower">-10</property>
-    <property name="page_increment">10</property>
-    <property name="step_increment">0.10000000000000001</property>
-    <property name="page_size">0</property>
-    <property name="value">1</property>
-  </object>
   <object class="GtkAdjustment" id="adjustment3">
     <property name="upper">65535</property>
     <property name="lower">1</property>
@@ -25,31 +9,6 @@
     <property name="page_size">0</property>
     <property name="value">10</property>
   </object>
-  <object class="GtkListStore" id="model1">
-    <columns>
-      <column type="gchararray"/>
-    </columns>
-    <data>
-      <row>
-        <col id="0" translatable="yes">Auto</col>
-      </row>
-      <row>
-        <col id="0" translatable="yes">Centered</col>
-      </row>
-      <row>
-        <col id="0" translatable="yes">Tiled</col>
-      </row>
-      <row>
-        <col id="0" translatable="yes">Stretched</col>
-      </row>
-      <row>
-        <col id="0" translatable="yes">Scaled</col>
-      </row>
-      <row>
-        <col id="0" translatable="yes">Zoomed</col>
-      </row>
-    </data>
-  </object>
   <object class="GtkListStore" id="model2">
     <columns>
       <column type="gchararray"/>
@@ -104,12 +63,10 @@
                             <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
                             <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
                             <child>
-                              <object class="GtkTreeView" id="treeview_imagelist">
+                              <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>
-                                <property name="headers_visible">False</property>
-                                <property name="search_column">1</property>
                               </object>
                             </child>
                           </object>
@@ -120,74 +77,32 @@
                             <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="GtkButton" id="btn_plus">
+                              <object class="GtkLabel" id="label_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>
-                                <signal handler="add_clicked" name="clicked"/>
-                                <child>
-                                  <object class="GtkImage" id="image1">
-                                    <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="stock">gtk-add</property>
-                                    <property name="icon_size">1</property>
-                                  </object>
-                                </child>
-                              </object>
-                              <packing>
-                                <property name="expand">False</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkButton" id="btn_minus">
-                                <property name="visible">True</property>
-                                <property name="sensitive">False</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">Remove the selected image(s) from the list</property>
-                                <signal handler="remove_clicked" name="clicked"/>
-                                <child>
-                                  <object class="GtkImage" id="image2">
-                                    <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="stock">gtk-remove</property>
-                                    <property name="icon_size">1</property>
-                                  </object>
-                                </child>
+                                <property name="label" translatable="yes">Folder:</property>
+                                <property name="use_underline">True</property>
                               </object>
                               <packing>
                                 <property name="expand">False</property>
-                                <property name="fill">False</property>
-                                <property name="position">1</property>
                               </packing>
                             </child>
                             <child>
-                              <object class="GtkButton" id="btn_newlist">
+                              <object class="GtkFileChooserButton" id="btn_folder">
                                 <property name="visible">True</property>
-                                <property name="sensitive">False</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">Create a new list, or load an existing one</property>
-                                <child>
-                                  <object class="GtkImage" id="image3">
-                                    <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="stock">gtk-new</property>
-                                    <property name="icon_size">1</property>
-                                  </object>
-                                </child>
+                                <property name="tooltip-text" translatable="yes">Add an image to the list</property>
+                                <property name="action">GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER</property>
+                                <property name="width-chars">30</property>
                               </object>
                               <packing>
                                 <property name="expand">False</property>
-                                <property name="position">4</property>
                               </packing>
                             </child>
                             <child>
-                              <object class="GtkLabel" id="label8">
+                              <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>
@@ -196,151 +111,39 @@
                               </object>
                               <packing>
                                 <property name="expand">False</property>
-                                <property name="padding">3</property>
-                                <property name="pack_type">GTK_PACK_END</property>
-                                <property name="position">3</property>
                               </packing>
                             </child>
                             <child>
-                              <object class="GtkComboBox" id="combo_style">
+                              <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"/>
-                                <property name="model">model1</property>
-                                <child>
-                                  <object class="GtkCellRendererText" id="renderer1"/>
-                                  <attributes>
-                                    <attribute name="text">0</attribute>
-                                  </attributes>
-                                </child>
+                                <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>
-                                <property name="position">2</property>
                               </packing>
                             </child>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="position">1</property>
-                          </packing>
-                        </child>
-                      </object>
-                    </child>
-                  </object>
-                </child>
-                <child type="label">
-                  <object class="GtkLabel" id="label4">
-                    <property name="visible">True</property>
-                    <property name="label" translatable="yes"><b>Images</b></property>
-                    <property name="use_markup">True</property>
-                  </object>
-                </child>
-              </object>
-            </child>
-            <child>
-              <object class="GtkVBox" id="vbox12">
-                <property name="visible">True</property>
-                <property name="spacing">6</property>
-                <child>
-                  <object class="GtkFrame" id="frame2">
-                    <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_xalign">0</property>
-                    <property name="shadow_type">GTK_SHADOW_NONE</property>
-                    <child>
-                      <object class="GtkAlignment" id="alignment2">
-                        <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="border_width">6</property>
-                        <property name="left_padding">6</property>
-                        <child>
-                          <object class="GtkVBox" id="vbox5">
-                            <property name="visible">True</property>
                             <child>
-                              <object class="GtkRadioButton" id="radio_singleimage">
+                              <object class="GtkLabel" id="label_color">
                                 <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="tooltip-text" translatable="yes">Select a single image as the backdrop</property>
-                                <property name="label" translatable="yes">_Single image</property>
+                                <property name="label" translatable="yes">Color:</property>
                                 <property name="use_underline">True</property>
-                                <property name="active">True</property>
-                                <property name="draw_indicator">True</property>
-                                <signal handler="image_type_changed" name="toggled"/>
                               </object>
                               <packing>
                                 <property name="expand">False</property>
                               </packing>
                             </child>
                             <child>
-                              <object class="GtkRadioButton" id="radio_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>
-                                <property name="tooltip-text" translatable="yes">Automatically pick a random image from a list file</property>
-                                <property name="label" translatable="yes">Image _list</property>
-                                <property name="use_underline">True</property>
-                                <property name="draw_indicator">True</property>
-                                <property name="group">radio_singleimage</property>
-                                <signal handler="image_type_changed" name="toggled"/>
-                              </object>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="position">1</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkRadioButton" id="radio_none">
-                                <property name="visible">True</property>
-                                <property name="can_focus">True</property>
-                                <property name="tooltip-text" translatable="yes">Don't display an image at all</property>
-                                <property name="label" translatable="yes">_None</property>
-                                <property name="use_underline">True</property>
-                                <property name="draw_indicator">True</property>
-                                <property name="group">radio_singleimage</property>
-                              </object>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="position">2</property>
-                              </packing>
-                            </child>
-                          </object>
-                        </child>
-                      </object>
-                    </child>
-                    <child type="label">
-                      <object class="GtkLabel" id="label9">
-                        <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"><b>Image</b></property>
-                        <property name="use_markup">True</property>
-                      </object>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkFrame" id="frame1">
-                    <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_xalign">0</property>
-                    <property name="shadow_type">GTK_SHADOW_NONE</property>
-                    <child>
-                      <object class="GtkAlignment" id="alignment3">
-                        <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="border_width">6</property>
-                        <property name="left_padding">6</property>
-                        <child>
-                          <object class="GtkVBox" id="vbox13">
-                            <property name="visible">True</property>
-                            <property name="spacing">6</property>
-                            <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>
@@ -359,182 +162,48 @@
                               </packing>
                             </child>
                             <child>
-                              <object class="GtkHBox" id="hbox2">
+                              <object class="GtkColorButton" id="color1_btn">
                                 <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="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>
-                                    <property name="position">1</property>
-                                  </packing>
-                                </child>
+                                <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="position">1</property>
+                                <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>
-                        </child>
-                      </object>
-                    </child>
-                    <child type="label">
-                      <object class="GtkLabel" id="label7">
-                        <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"><b>Colors</b></property>
-                        <property name="use_markup">True</property>
-                      </object>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="position">1</property>
-                  </packing>
-                </child>
-              </object>
-              <packing>
-                <property name="position">1</property>
-                <property name="expand">False</property>
-              </packing>
-            </child>
-          </object>
-        </child>
-        <child>
-          <object class="GtkFrame" id="frame3">
-            <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_xalign">0</property>
-            <property name="shadow_type">GTK_SHADOW_NONE</property>
-            <child>
-              <object class="GtkAlignment" id="alignment4">
-                <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="border_width">6</property>
-                <property name="left_padding">6</property>
-                <child>
-                  <object class="GtkVBox" id="vbox14">
-                    <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">6</property>
-                    <child>
-                      <object class="GtkHBox" id="hbox5">
-                        <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="GtkLabel" id="label19">
-                            <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">B_rightness:</property>
-                            <property name="use_underline">True</property>
-                            <property name="mnemonic_widget">slider_brightness</property>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkHScale" id="slider_brightness">
-                            <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="tooltip-text" translatable="yes">Increase or decrease the brightness of the final image</property>
-                            <property name="update_policy">GTK_UPDATE_DISCONTINUOUS</property>
-                            <property name="adjustment">adjustment1</property>
-                            <property name="digits">0</property>
-                            <property name="value_pos">GTK_POS_RIGHT</property>
-                            <signal handler="brightness_changed" name="value_changed"/>
-                          </object>
-                          <packing>
-                            <property name="position">1</property>
-                          </packing>
-                        </child>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkHBox" id="hbox6">
-                        <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="GtkLabel" id="label20">
-                            <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">Sa_turation:</property>
-                            <property name="use_underline">True</property>
-                            <property name="mnemonic_widget">slider_saturation</property>
                           </object>
                           <packing>
                             <property name="expand">False</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkHScale" id="slider_saturation">
-                            <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="tooltip-text" translatable="yes">Increase or decrease the color saturation of the final image</property>
-                            <property name="update_policy">GTK_UPDATE_DISCONTINUOUS</property>
-                            <property name="adjustment">adjustment2</property>
-                            <property name="value_pos">GTK_POS_RIGHT</property>
-                            <signal handler="saturation_changed" name="value_changed"/>
-                          </object>
-                          <packing>
                             <property name="position">1</property>
                           </packing>
                         </child>
                       </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="position">1</property>
-                      </packing>
                     </child>
                   </object>
                 </child>
               </object>
             </child>
-            <child type="label">
-              <object class="GtkLabel" id="label21">
-                <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"><b>Adjustments</b></property>
-                <property name="use_markup">True</property>
-              </object>
-            </child>
           </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="position">1</property>
-          </packing>
         </child>
         <child>
           <object class="GtkHBox" id="hbox9">
@@ -544,11 +213,11 @@
             <child>
               <object class="GtkCheckButton" id="chk_cycle_backdrop">
                 <property name="visible">True</property>
-                <property name="sensitive">False</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">While in image list mode, select this option to automatically select a different background from the image list after a set number of 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>
@@ -563,35 +232,33 @@
               <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 randomly selected from the list.</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>
-      <child>
-        <object class="GtkCheckButton" id="chk_xinerama_stretch">
-          <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">St_retch this background across all monitors.</property>
-          <property name="tooltip-text" translatable="yes">When multiple monitors are present, select this option to stretch the current background over all of them.</property>
-          <property name="use_underline">True</property>
-          <property name="draw_indicator">True</property>
-        </object>
-        <packing>
-          <property name="expand">False</property>
-          <property name="position">3</property>
-        </packing>
-      </child>
       </object>
     </child>
   </object>
diff --git a/settings/xfdesktop-settings-ui.glade b/settings/xfdesktop-settings-ui.glade
index eef177e..7bccb6b 100644
--- a/settings/xfdesktop-settings-ui.glade
+++ b/settings/xfdesktop-settings-ui.glade
@@ -1,22 +1,6 @@
 <?xml version="1.0"?>
 <!--Generated with glade3 3.4.5 on Sun Nov 16 16:39:43 2008 -->
 <interface>
-  <object class="GtkAdjustment" id="adjustment1">
-    <property name="upper">127</property>
-    <property name="lower">-128</property>
-    <property name="page_increment">10</property>
-    <property name="step_increment">1</property>
-    <property name="page_size">0</property>
-    <property name="value">0</property>
-  </object>
-  <object class="GtkAdjustment" id="adjustment2">
-    <property name="upper">10</property>
-    <property name="lower">-10</property>
-    <property name="page_increment">10</property>
-    <property name="step_increment">0.10000000000000001</property>
-    <property name="page_size">0</property>
-    <property name="value">1</property>
-  </object>
   <object class="GtkAdjustment" id="adjustment3">
     <property name="upper">192</property>
     <property name="lower">8</property>
@@ -33,58 +17,6 @@
     <property name="page_size">0</property>
     <property name="value">12</property>
   </object>
-  <object class="GtkAdjustment" id="adjustment5">
-    <property name="upper">100</property>
-    <property name="lower">0</property>
-    <property name="page_increment">10</property>
-    <property name="step_increment">1</property>
-    <property name="page_size">0</property>
-    <property name="value">40</property>
-  </object>
-  <object class="GtkListStore" id="model1">
-    <columns>
-      <column type="gchararray"/>
-    </columns>
-    <data>
-      <row>
-        <col id="0" translatable="yes">Auto</col>
-      </row>
-      <row>
-        <col id="0" translatable="yes">Centered</col>
-      </row>
-      <row>
-        <col id="0" translatable="yes">Tiled</col>
-      </row>
-      <row>
-        <col id="0" translatable="yes">Stretched</col>
-      </row>
-      <row>
-        <col id="0" translatable="yes">Scaled</col>
-      </row>
-      <row>
-        <col id="0" translatable="yes">Zoomed</col>
-      </row>
-    </data>
-  </object>
-  <object class="GtkListStore" id="model2">
-    <columns>
-      <column type="gchararray"/>
-    </columns>
-    <data>
-      <row>
-        <col id="0" translatable="yes">Solid color</col>
-      </row>
-      <row>
-        <col id="0" translatable="yes">Horizontal gradient</col>
-      </row>
-      <row>
-        <col id="0" translatable="yes">Vertical gradient</col>
-      </row>
-      <row>
-        <col id="0" translatable="yes">Transparent</col>
-      </row>
-    </data>
-  </object>
   <object class="GtkListStore" id="model3">
     <columns>
       <column type="gchararray"/>
@@ -179,6 +111,8 @@
     <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
     <property name="has_separator">False</property>
     <property name="subtitle" translatable="yes">Set desktop background and menu and icon behavior</property>
+    <property name="default-width">640</property>
+    <property name="default-height">480</property>
     <child internal-child="vbox">
       <object class="GtkVBox" id="dialog-vbox1">
         <property name="visible">True</property>
@@ -194,14 +128,9 @@
                 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
                 <property name="border_width">6</property>
                 <child>
-                  <object class="GtkNotebook" id="notebook_screens">
+                  <object class="GtkTable" id="notebook_screens">
                     <property name="visible">True</property>
                     <property name="can_focus">True</property>
-                    <property name="show_tabs">False</property>
-                    <property name="show_border">False</property>
-                    <child type="tab">
-                      <placeholder/>
-                    </child>
                   </object>
                 </child>
                 <child type="tab">
@@ -742,40 +671,6 @@
                                     <property name="position">2</property>
                                   </packing>
                                 </child>
-                                <child>
-                                  <object class="GtkHBox" id="hbox10">
-                                    <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="GtkLabel" id="label16">
-                                        <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">Label trans_parency:</property>
-                                        <property name="use_underline">True</property>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkHScale" id="hscale3">
-                                        <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="tooltip-text" translatable="yes">Specify the transparency level for the rounded label drawn behind the icon text</property>
-                                        <property name="adjustment">adjustment5</property>
-                                        <property name="digits">0</property>
-                                        <property name="value_pos">GTK_POS_RIGHT</property>
-                                      </object>
-                                      <packing>
-                                        <property name="position">1</property>
-                                      </packing>
-                                    </child>
-                                  </object>
-                                  <packing>
-                                    <property name="position">3</property>
-                                  </packing>
-                                </child>
                               </object>
                             </child>
                           </object>
diff --git a/src/Makefile.am b/src/Makefile.am
index adeac0b..4d73dad 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -22,6 +22,8 @@ xfdesktop_SOURCES = \
 	windowlist.h \
 	xfce-backdrop.c \
 	xfce-backdrop.h \
+	xfce-workspace.c \
+	xfce-workspace.h \
 	xfce-desktop.c \
 	xfce-desktop.h
 
diff --git a/src/xfce-backdrop.c b/src/xfce-backdrop.c
index 58c98c8..4b3a909 100644
--- a/src/xfce-backdrop.c
+++ b/src/xfce-backdrop.c
@@ -64,18 +64,16 @@ struct _XfceBackdropPriv
     XfceBackdropColorStyle color_style;
     GdkColor color1;
     GdkColor color2;
-    
-    gboolean show_image;
+
     XfceBackdropImageStyle image_style;
     gchar *image_path;
-    gchar *backdrop_list;
-    
+
     gint brightness;
-    gdouble saturation;
 
     gboolean cycle_backdrop;
     guint cycle_timer;
     guint cycle_timer_id;
+    gboolean random_backdrop_order;
 };
 
 enum
@@ -91,13 +89,12 @@ enum
     PROP_COLOR_STYLE,
     PROP_COLOR1,
     PROP_COLOR2,
-    PROP_SHOW_IMAGE,
     PROP_IMAGE_STYLE,
     PROP_IMAGE_FILENAME,
     PROP_BRIGHTNESS,
-    PROP_SATURATION,
     PROP_BACKDROP_CYCLE_ENABLE,
     PROP_BACKDROP_CYCLE_TIMER,
+    PROP_BACKDROP_RANDOM_ORDER
 };
 
 static guint backdrop_signals[LAST_SIGNAL] = { 0, };
@@ -284,19 +281,12 @@ xfce_backdrop_class_init(XfceBackdropClass *klass)
                                                        GDK_TYPE_COLOR,
                                                        XFDESKTOP_PARAM_FLAGS));
 
-    g_object_class_install_property(gobject_class, PROP_SHOW_IMAGE,
-                                    g_param_spec_boolean("show-image",
-                                                         "show image",
-                                                         "show image",
-                                                         TRUE,
-                                                         XFDESKTOP_PARAM_FLAGS));
-
     g_object_class_install_property(gobject_class, PROP_IMAGE_STYLE,
                                     g_param_spec_enum("image-style",
                                                       "image style",
                                                       "image style",
                                                       XFCE_TYPE_BACKDROP_IMAGE_STYLE,
-                                                      XFCE_BACKDROP_IMAGE_AUTO,
+                                                      XFCE_BACKDROP_IMAGE_SCALED,
                                                       XFDESKTOP_PARAM_FLAGS));
 
     g_object_class_install_property(gobject_class, PROP_IMAGE_FILENAME,
@@ -313,13 +303,6 @@ xfce_backdrop_class_init(XfceBackdropClass *klass)
                                                      -128, 127, 0,
                                                      XFDESKTOP_PARAM_FLAGS));
 
-    g_object_class_install_property(gobject_class, PROP_SATURATION,
-                                    g_param_spec_double("saturation",
-                                                        "saturation",
-                                                        "saturation",
-                                                        -10.0, 10.0, 1.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",
@@ -334,6 +317,13 @@ xfce_backdrop_class_init(XfceBackdropClass *klass)
                                                      0, G_MAXUSHORT, 10,
                                                      XFDESKTOP_PARAM_FLAGS));
 
+    g_object_class_install_property(gobject_class, PROP_BACKDROP_RANDOM_ORDER,
+                                    g_param_spec_boolean("backdrop-cycle-random-order",
+                                                         "backdrop-cycle-random-order",
+                                                         "backdrop-cycle-random-order",
+                                                         FALSE,
+                                                         XFDESKTOP_PARAM_FLAGS));
+
 #undef XFDESKTOP_PARAM_FLAGS
 }
 
@@ -342,9 +332,7 @@ xfce_backdrop_init(XfceBackdrop *backdrop)
 {
     backdrop->priv = G_TYPE_INSTANCE_GET_PRIVATE(backdrop, XFCE_TYPE_BACKDROP,
                                                  XfceBackdropPriv);
-    backdrop->priv->show_image = TRUE;
     backdrop->priv->cycle_timer_id = 0;
-    backdrop->priv->backdrop_list = NULL;
 
     /* color defaults */
     backdrop->priv->color1.red = 0x1515;
@@ -370,11 +358,6 @@ xfce_backdrop_finalize(GObject *object)
         backdrop->priv->cycle_timer_id = 0;
     }
 
-    if(backdrop->priv->backdrop_list != NULL) {
-        g_free(backdrop->priv->backdrop_list);
-        backdrop->priv->backdrop_list = NULL;
-    }
-
     G_OBJECT_CLASS(xfce_backdrop_parent_class)->finalize(object);
 }
 
@@ -404,10 +387,6 @@ xfce_backdrop_set_property(GObject *object,
                 xfce_backdrop_set_second_color(backdrop, color);
             break;
 
-        case PROP_SHOW_IMAGE:
-            xfce_backdrop_set_show_image(backdrop, g_value_get_boolean(value));
-            break;
-
         case PROP_IMAGE_STYLE:
             xfce_backdrop_set_image_style(backdrop, g_value_get_enum(value));
             break;
@@ -421,10 +400,6 @@ xfce_backdrop_set_property(GObject *object,
             xfce_backdrop_set_brightness(backdrop, g_value_get_int(value));
             break;
 
-        case PROP_SATURATION:
-            xfce_backdrop_set_saturation(backdrop, g_value_get_double(value));
-            break;
-
         case PROP_BACKDROP_CYCLE_ENABLE:
             xfce_backdrop_set_cycle_backdrop(backdrop, g_value_get_boolean(value));
             break;
@@ -433,6 +408,10 @@ xfce_backdrop_set_property(GObject *object,
             xfce_backdrop_set_cycle_timer(backdrop, g_value_get_uint(value));
             break;
 
+        case PROP_BACKDROP_RANDOM_ORDER:
+            xfce_backdrop_set_random_order(backdrop, g_value_get_boolean(value));
+            break;
+
         default:
             G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
             break;
@@ -460,10 +439,6 @@ xfce_backdrop_get_property(GObject *object,
             g_value_set_boxed(value, &backdrop->priv->color2);
             break;
 
-        case PROP_SHOW_IMAGE:
-            g_value_set_boolean(value, xfce_backdrop_get_show_image(backdrop));
-            break;
-
         case PROP_IMAGE_STYLE:
             g_value_set_enum(value, xfce_backdrop_get_image_style(backdrop));
             break;
@@ -477,10 +452,6 @@ xfce_backdrop_get_property(GObject *object,
             g_value_set_int(value, xfce_backdrop_get_brightness(backdrop));
             break;
 
-        case PROP_SATURATION:
-            g_value_set_double(value, xfce_backdrop_get_saturation(backdrop));
-            break;
-
         case PROP_BACKDROP_CYCLE_ENABLE:
             g_value_set_boolean(value, xfce_backdrop_get_cycle_backdrop(backdrop));
             break;
@@ -489,6 +460,10 @@ xfce_backdrop_get_property(GObject *object,
             g_value_set_uint(value, xfce_backdrop_get_cycle_timer(backdrop));
             break;
 
+        case PROP_BACKDROP_RANDOM_ORDER:
+            g_value_set_boolean(value, xfce_backdrop_get_random_order(backdrop));
+            break;
+
         default:
             G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
             break;
@@ -670,32 +645,6 @@ xfce_backdrop_get_second_color(XfceBackdrop *backdrop,
 }
 
 /**
- * xfce_backdrop_set_show_image:
- * @backdrop: An #XfceBackdrop.
- * @show_image: Whether or not to composite the image on top of the color.
- *
- * Sets whether or not the #XfceBackdrop should consist of an image composited
- * on top of a color (or color gradient), or just a color (or color gradient).
- **/
-void
-xfce_backdrop_set_show_image(XfceBackdrop *backdrop, gboolean show_image)
-{
-    g_return_if_fail(XFCE_IS_BACKDROP(backdrop));
-    
-    if(backdrop->priv->show_image != show_image) {
-        backdrop->priv->show_image = show_image;
-        g_signal_emit(G_OBJECT(backdrop), backdrop_signals[BACKDROP_CHANGED], 0);
-    }
-}
-
-gboolean
-xfce_backdrop_get_show_image(XfceBackdrop *backdrop)
-{
-    g_return_val_if_fail(XFCE_IS_BACKDROP(backdrop), FALSE);
-    return backdrop->priv->show_image;
-}
-
-/**
  * xfce_backdrop_set_image_style:
  * @backdrop: An #XfceBackdrop.
  * @style: An XfceBackdropImageStyle.
@@ -739,7 +688,9 @@ void
 xfce_backdrop_set_image_filename(XfceBackdrop *backdrop, const gchar *filename)
 {
     g_return_if_fail(XFCE_IS_BACKDROP(backdrop));
-    
+
+    TRACE("entering");
+
     g_free(backdrop->priv->image_path);
     
     if(filename)
@@ -758,37 +709,6 @@ xfce_backdrop_get_image_filename(XfceBackdrop *backdrop)
 }
 
 /**
- * xfce_backdrop_set_list:
- * @backdrop: An #XfceBackdrop.
- * @backdrop_list: A list of backdrop images.
- *
- * Sets the internal list of wallpaper images assigned to this backdrop.
- * Frees any previous backdrop list before setting the new one.
- * [Transfer full]
- **/
-void
-xfce_backdrop_set_list(XfceBackdrop *backdrop,
-                       gchar *backdrop_list)
-{
-    g_return_if_fail(XFCE_IS_BACKDROP(backdrop));
-
-    if(backdrop->priv->backdrop_list != NULL) {
-        g_free(backdrop->priv->backdrop_list);
-        backdrop->priv->backdrop_list = NULL;
-    }
-
-    backdrop->priv->backdrop_list = backdrop_list;
-}
-
-G_CONST_RETURN gchar*
-xfce_backdrop_get_list(XfceBackdrop *backdrop)
-{
-    g_return_val_if_fail(XFCE_IS_BACKDROP(backdrop), NULL);
-
-    return backdrop->priv->backdrop_list;
-}
-
-/**
  * xfce_backdrop_set_brightness:
  * @backdrop: An #XfceBackdrop.
  * @brightness: A brightness value.
@@ -815,24 +735,6 @@ xfce_backdrop_get_brightness(XfceBackdrop *backdrop)
     return backdrop->priv->brightness;
 }
 
-void
-xfce_backdrop_set_saturation(XfceBackdrop *backdrop,
-                             gdouble saturation)
-{
-    g_return_if_fail(XFCE_IS_BACKDROP(backdrop));
-    if(abs(saturation - backdrop->priv->saturation) > 0.05) {
-        backdrop->priv->saturation = saturation;
-        g_signal_emit(G_OBJECT(backdrop), backdrop_signals[BACKDROP_CHANGED], 0);
-    }
-}
-
-gdouble
-xfce_backdrop_get_saturation(XfceBackdrop *backdrop)
-{
-    g_return_val_if_fail(XFCE_IS_BACKDROP(backdrop), 1.0);
-    return backdrop->priv->saturation;
-}
-
 static gboolean
 xfce_backdrop_timer(XfceBackdrop *backdrop)
 {
@@ -911,6 +813,25 @@ xfce_backdrop_get_cycle_backdrop(XfceBackdrop *backdrop)
     return backdrop->priv->cycle_backdrop;
 }
 
+void
+xfce_backdrop_set_random_order(XfceBackdrop *backdrop,
+                               gboolean random_order)
+{
+    g_return_if_fail(XFCE_IS_BACKDROP(backdrop));
+
+    TRACE("entering");
+
+    backdrop->priv->random_backdrop_order = random_order;
+}
+
+gboolean
+xfce_backdrop_get_random_order(XfceBackdrop *backdrop)
+{
+    g_return_val_if_fail(XFCE_IS_BACKDROP(backdrop), FALSE);
+
+    return backdrop->priv->random_backdrop_order;
+}
+
 /**
  * xfce_backdrop_get_pixbuf:
  * @backdrop: An #XfceBackdrop.
@@ -933,8 +854,10 @@ xfce_backdrop_get_pixbuf(XfceBackdrop *backdrop)
     
     g_return_val_if_fail(XFCE_IS_BACKDROP(backdrop), NULL);
     
-    if(backdrop->priv->show_image && backdrop->priv->image_path)
+    if(backdrop->priv->image_style != XFCE_BACKDROP_IMAGE_NONE &&
+       backdrop->priv->image_path) {
         gdk_pixbuf_get_file_info(backdrop->priv->image_path, &iw, &ih);
+    }
 
     if(backdrop->priv->width == 0 || backdrop->priv->height == 0) {
         w = iw;
@@ -965,13 +888,7 @@ xfce_backdrop_get_pixbuf(XfceBackdrop *backdrop)
         return final_image;
     }
     
-    if(backdrop->priv->image_style == XFCE_BACKDROP_IMAGE_AUTO) {
-        if(ih <= h / 2 && iw <= w / 2)
-            istyle = XFCE_BACKDROP_IMAGE_TILED;
-        else
-            istyle = XFCE_BACKDROP_IMAGE_ZOOMED;
-    } else
-        istyle = backdrop->priv->image_style;
+    istyle = backdrop->priv->image_style;
     
     /* if the image is the same as the screen size, there's no reason to do
      * any scaling at all */
@@ -1030,6 +947,7 @@ 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,
@@ -1088,12 +1006,6 @@ xfce_backdrop_get_pixbuf(XfceBackdrop *backdrop)
     
     if(backdrop->priv->brightness != 0)
         final_image = adjust_brightness(final_image, backdrop->priv->brightness);
-
-    if(backdrop->priv->saturation > 1.01 || backdrop->priv->saturation < 0.99) {
-        gdk_pixbuf_saturate_and_pixelate(final_image, final_image,
-                                         (gfloat)backdrop->priv->saturation,
-                                         FALSE);
-    }
     
     return final_image;
 }
diff --git a/src/xfce-backdrop.h b/src/xfce-backdrop.h
index 78ba6b0..6c013c3 100644
--- a/src/xfce-backdrop.h
+++ b/src/xfce-backdrop.h
@@ -40,12 +40,13 @@ typedef struct _XfceBackdropPriv XfceBackdropPriv;
 
 typedef enum
 {
-    XFCE_BACKDROP_IMAGE_AUTO = 0,
+    XFCE_BACKDROP_IMAGE_NONE = 0,
     XFCE_BACKDROP_IMAGE_CENTERED,
     XFCE_BACKDROP_IMAGE_TILED,
     XFCE_BACKDROP_IMAGE_STRETCHED,
     XFCE_BACKDROP_IMAGE_SCALED,
     XFCE_BACKDROP_IMAGE_ZOOMED,
+    XFCE_BACKDROP_IMAGE_SPANNING_SCREENS,
 } XfceBackdropImageStyle;
 
 typedef enum
@@ -100,10 +101,6 @@ void xfce_backdrop_set_second_color      (XfceBackdrop *backdrop,
 void xfce_backdrop_get_second_color      (XfceBackdrop *backdrop,
                                           GdkColor *color);
 
-void xfce_backdrop_set_show_image        (XfceBackdrop *backdrop,
-                                          gboolean show_image);
-gboolean xfce_backdrop_get_show_image    (XfceBackdrop *backdrop);
-
 void xfce_backdrop_set_image_style       (XfceBackdrop *backdrop,
                                           XfceBackdropImageStyle style);
 XfceBackdropImageStyle xfce_backdrop_get_image_style
@@ -114,19 +111,11 @@ void xfce_backdrop_set_image_filename    (XfceBackdrop *backdrop,
 G_CONST_RETURN gchar *xfce_backdrop_get_image_filename
                                          (XfceBackdrop *backdrop);
 
-void xfce_backdrop_set_list              (XfceBackdrop *backdrop,
-                                          gchar *backdrop_list);
-G_CONST_RETURN gchar *xfce_backdrop_get_list
-                                         (XfceBackdrop *backdrop);
 
 void xfce_backdrop_set_brightness        (XfceBackdrop *backdrop,
                                           gint brightness);
 gint xfce_backdrop_get_brightness        (XfceBackdrop *backdrop);
 
-void xfce_backdrop_set_saturation        (XfceBackdrop *backdrop,
-                                          gdouble saturation);
-gdouble xfce_backdrop_get_saturation     (XfceBackdrop *backdrop);
-
 void xfce_backdrop_set_cycle_backdrop    (XfceBackdrop *backdrop,
                                           gboolean cycle_backdrop);
 gboolean xfce_backdrop_get_cycle_backdrop(XfceBackdrop *backdrop);
@@ -135,6 +124,10 @@ void xfce_backdrop_set_cycle_timer       (XfceBackdrop *backdrop,
                                           guint cycle_timer);
 guint xfce_backdrop_get_cycle_timer      (XfceBackdrop *backdrop);
 
+void xfce_backdrop_set_random_order      (XfceBackdrop *backdrop,
+                                          gboolean random_order);
+gboolean xfce_backdrop_get_random_order  (XfceBackdrop *backdrop);
+
 GdkPixbuf *xfce_backdrop_get_pixbuf      (XfceBackdrop *backdrop);
 
 G_END_DECLS
diff --git a/src/xfce-desktop.c b/src/xfce-desktop.c
index b3f3d29..95c30f6 100644
--- a/src/xfce-desktop.c
+++ b/src/xfce-desktop.c
@@ -77,10 +77,12 @@
 #include <libxfce4ui/libxfce4ui.h>
 
 #include <xfconf/xfconf.h>
+#include <libwnck/libwnck.h>
 
 #include "xfdesktop-common.h"
 #include "xfce-desktop.h"
 #include "xfce-desktop-enum-types.h"
+#include "xfce-workspace.h"
 
 /* disable setting the x background for bug 7442 */
 //#define DISABLE_FOR_BUG7442
@@ -88,6 +90,7 @@
 struct _XfceDesktopPriv
 {
     GdkScreen *gscreen;
+    WnckScreen *wnck_screen;
     gboolean updates_frozen;
 
     XfconfChannel *channel;
@@ -95,10 +98,9 @@ struct _XfceDesktopPriv
     
     GdkPixmap *bg_pixmap;
     
-    guint nbackdrops;
-    XfceBackdrop **backdrops;
-    
-    gboolean xinerama_stretch;
+    gint nworkspaces;
+    XfceWorkspace **workspaces;
+    gint current_workspace;
     
     SessionLogoutFunc session_logout_func;
     
@@ -122,7 +124,6 @@ enum
 enum
 {
     PROP_0 = 0,
-    PROP_XINERAMA_STRETCH,
 #ifdef ENABLE_DESKTOP_ICONS
     PROP_ICON_STYLE,
     PROP_ICON_SIZE,
@@ -155,9 +156,7 @@ static gboolean xfce_desktop_delete_event(GtkWidget *w,
 static void xfce_desktop_style_set(GtkWidget *w,
                                    GtkStyle *old_style);
 
-static void xfce_desktop_connect_backdrop_settings(XfceDesktop *desktop,
-                                                   XfceBackdrop *backdrop,
-                                                   guint monitor);
+static gint xfce_desktop_get_current_workspace(XfceDesktop *desktop);
 
 static guint signals[N_SIGNALS] = { 0, };
 
@@ -173,9 +172,6 @@ xfce_desktop_ensure_system_font_size(XfceDesktop *desktop)
     PangoFontDescription *pfd;
     
     gscreen = gtk_widget_get_screen(GTK_WIDGET(desktop));
-    /* FIXME: needed? */
-    if(!gscreen)
-        gscreen = gdk_display_get_default_screen(gdk_display_get_default());
     
     settings = gtk_settings_get_for_screen(gscreen);
     g_object_get(G_OBJECT(settings), "gtk-font-name", &font_name, NULL);
@@ -314,8 +310,7 @@ backdrop_changed_cb(XfceBackdrop *backdrop, gpointer user_data)
     cairo_t *cr;
     GdkPixbuf *pix;
     GdkRectangle rect;
-    guint i;
-    gint monitor = -1;
+    gint i, monitor = -1, current_workspace;
     
     TRACE("entering");
     
@@ -325,30 +320,36 @@ backdrop_changed_cb(XfceBackdrop *backdrop, gpointer user_data)
         return;
     
     TRACE("really entering");
-    
-    for(i = 0; i < XFCE_DESKTOP(desktop)->priv->nbackdrops; i++) {
-        if(backdrop == XFCE_DESKTOP(desktop)->priv->backdrops[i]) {
+
+    current_workspace = xfce_desktop_get_current_workspace(desktop);
+
+    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;
             break;
         }
     }
     if(monitor == -1)
         return;
-    
+
+
+    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(desktop->priv->xinerama_stretch) {
+    if(xfce_desktop_get_n_monitors(desktop) > 1
+       && xfce_workspace_get_xinerama_stretch(desktop->priv->workspaces[current_workspace])) {
         GdkRectangle monitor_rect;
 
         gdk_screen_get_monitor_geometry(gscreen, 0, &rect);
-
         /* Get the lowest x and y value for all the monitors in
          * case none of them start at 0,0 for whatever reason.
          */
-        for(i = 1; i < (guint)gdk_screen_get_n_monitors(gscreen); i++) {
+        for(i = 1; i < xfce_desktop_get_n_monitors(desktop); i++) {
             gdk_screen_get_monitor_geometry(gscreen, i, &monitor_rect);
 
             if(monitor_rect.x < rect.x)
@@ -382,36 +383,16 @@ backdrop_changed_cb(XfceBackdrop *backdrop, gpointer user_data)
 }
 
 static void
-backdrop_cycle_cb(XfceBackdrop *backdrop, gpointer user_data)
+screen_size_changed_cb(GdkScreen *gscreen, gpointer user_data)
 {
-    const gchar* backdrop_list;
+    XfceDesktop *desktop = user_data;
+    gint w, h, current_workspace;
+    XfceBackdrop *current_backdrop;
 
     TRACE("entering");
 
-    g_return_if_fail(XFCE_IS_BACKDROP(backdrop));
-
-    backdrop_list = xfce_backdrop_get_list(backdrop);
-
-    if(xfdesktop_backdrop_list_is_valid(backdrop_list)) {
-        gchar *backdrop_file;
-        GError *error = NULL;
-
-        backdrop_file = xfdesktop_backdrop_list_choose_random(backdrop_list,
-                                                              &error);
-
-        xfce_backdrop_set_image_filename(backdrop, backdrop_file);
-        g_free(backdrop_file);
-        backdrop_changed_cb(backdrop, user_data);
-    }
-}
-
-static void
-screen_size_changed_cb(GdkScreen *gscreen, gpointer user_data)
-{
-    XfceDesktop *desktop = user_data;
-    gint w, h;
-    
     g_return_if_fail(XFCE_IS_DESKTOP(desktop));
+    g_return_if_fail(desktop->priv->workspaces);
     
     w = gdk_screen_get_width(gscreen);
     h = gdk_screen_get_height(gscreen);
@@ -426,20 +407,26 @@ screen_size_changed_cb(GdkScreen *gscreen, gpointer user_data)
                                 desktop->priv->bg_pixmap);
     gdk_window_set_back_pixmap(gtk_widget_get_window(GTK_WIDGET(desktop)),
                                desktop->priv->bg_pixmap, FALSE);
-    
+
+    current_workspace = xfce_desktop_get_current_workspace(desktop);
+
+    if(desktop->priv->nworkspaces <= current_workspace)
+        return;
+
     /* special case for 1 backdrop to handle xinerama stretching */
-    if(desktop->priv->xinerama_stretch) {
-        xfce_backdrop_set_size(desktop->priv->backdrops[0], w, h);
-        backdrop_changed_cb(desktop->priv->backdrops[0], desktop);
+    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;
-        guint i;
+        gint i;
 
-        for(i = 0; i < desktop->priv->nbackdrops; i++) {
+        for(i = 0; i < xfce_desktop_get_n_monitors(desktop); i++) {
             gdk_screen_get_monitor_geometry(gscreen, i, &rect);
-            xfce_backdrop_set_size(desktop->priv->backdrops[i], rect.width,
-                                   rect.height);
-            backdrop_changed_cb(desktop->priv->backdrops[i], desktop);
+            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);
         }
     }
 }
@@ -448,6 +435,7 @@ static void
 screen_composited_changed_cb(GdkScreen *gscreen,
                              gpointer user_data)
 {
+    TRACE("entering");
     /* fake a screen size changed, so the background is properly set */
     screen_size_changed_cb(gscreen, user_data);
 }
@@ -457,66 +445,110 @@ xfce_desktop_monitors_changed(GdkScreen *gscreen,
                               gpointer user_data)
 {
     XfceDesktop *desktop = XFCE_DESKTOP(user_data);
-    guint i;
+    gint i;
 
-    if(desktop->priv->xinerama_stretch) {
-        if(desktop->priv->nbackdrops > 1) {
-            for(i = 1; i < desktop->priv->nbackdrops; ++i)
-                g_object_unref(G_OBJECT(desktop->priv->backdrops[i]));
-        }
+    TRACE("entering");
 
-        if(desktop->priv->nbackdrops != 1) {
-            desktop->priv->backdrops = g_realloc(desktop->priv->backdrops,
-                                                 sizeof(XfceBackdrop *));
-            if(!desktop->priv->nbackdrops) {
-                GdkVisual *vis = gtk_widget_get_visual(GTK_WIDGET(desktop));
-                desktop->priv->backdrops[0] = xfce_backdrop_new(vis);
-                xfce_desktop_connect_backdrop_settings(desktop,
-                                                       desktop->priv->backdrops[0],
-                                                       0);
-                g_signal_connect(G_OBJECT(desktop->priv->backdrops[0]),
-                                 "changed",
-                                 G_CALLBACK(backdrop_changed_cb), desktop);
-                g_signal_connect(G_OBJECT(desktop->priv->backdrops[0]),
-                                 "cycle",
-                                 G_CALLBACK(backdrop_cycle_cb), desktop);
-            }
-            desktop->priv->nbackdrops = 1;
-        }
-    } else {
-        guint n_monitors = gdk_screen_get_n_monitors(gscreen);
+    /* Update the workspaces */
+    for(i = 0; i < desktop->priv->nworkspaces; i++) {
+        xfce_workspace_monitors_changed(desktop->priv->workspaces[i],
+                                        gscreen);
+    }
 
-        if(n_monitors < desktop->priv->nbackdrops) {
-            for(i = n_monitors; i < desktop->priv->nbackdrops; ++i)
-                g_object_unref(G_OBJECT(desktop->priv->backdrops[i]));
-        }
+    /* fake a screen size changed, so the background is properly set */
+    screen_size_changed_cb(gscreen, user_data);
+}
 
-        if(n_monitors != desktop->priv->nbackdrops) {
-            desktop->priv->backdrops = g_realloc(desktop->priv->backdrops,
-                                                 sizeof(XfceBackdrop *) * n_monitors);
-            if(n_monitors > desktop->priv->nbackdrops) {
-                GdkVisual *vis = gtk_widget_get_visual(GTK_WIDGET(desktop));
-                for(i = desktop->priv->nbackdrops; i < n_monitors; ++i) {
-                    desktop->priv->backdrops[i] = xfce_backdrop_new(vis);
-                    xfce_desktop_connect_backdrop_settings(desktop,
-                                                           desktop->priv->backdrops[i],
-                                                           i);
-                    g_signal_connect(G_OBJECT(desktop->priv->backdrops[i]),
-                                     "changed",
-                                     G_CALLBACK(backdrop_changed_cb),
-                                     desktop);
-                    g_signal_connect(G_OBJECT(desktop->priv->backdrops[i]),
-                                     "cycle",
-                                     G_CALLBACK(backdrop_cycle_cb),
-                                     desktop);
-                }
-            }
-            desktop->priv->nbackdrops = n_monitors;
-        }
-    }
+static void
+workspace_backdrop_changed_cb(XfceWorkspace *workspace,
+                              XfceBackdrop  *backdrop,
+                              gpointer user_data)
+{
+    XfceDesktop *desktop = XFCE_DESKTOP(user_data);
+
+    TRACE("entering");
+
+    g_return_if_fail(XFCE_IS_WORKSPACE(workspace) && XFCE_IS_BACKDROP(backdrop));
+
+    if(desktop->priv->current_workspace == xfce_workspace_get_workspace_num(workspace))
+        backdrop_changed_cb(backdrop, user_data);
+}
+
+static void
+workspace_changed_cb(WnckScreen *wnck_screen,
+                     WnckWorkspace *previously_active_space,
+                     gpointer user_data)
+{
+    XfceDesktop *desktop = XFCE_DESKTOP(user_data);
+    WnckWorkspace *wnck_workspace = wnck_screen_get_active_workspace(wnck_screen);
+
+    TRACE("entering");
+
+    desktop->priv->current_workspace = wnck_workspace_get_number(wnck_workspace);
+
+    /* fake a screen size changed, so the background is properly set */
+    screen_size_changed_cb(desktop->priv->gscreen, user_data);
+}
+
+static void
+workspace_created_cb(WnckScreen *wnck_screen,
+                     WnckWorkspace *new_workspace,
+                     gpointer user_data)
+{
+    XfceDesktop *desktop = XFCE_DESKTOP(user_data);
+    gint nlast_workspace;
+    TRACE("entering");
+
+    nlast_workspace = desktop->priv->nworkspaces;
+
+    /* add one more workspace */
+    desktop->priv->nworkspaces = nlast_workspace + 1;
+
+    /* allocate size for it */
+    desktop->priv->workspaces = g_realloc(desktop->priv->workspaces,
+                                          desktop->priv->nworkspaces * sizeof(XfceWorkspace *));
 
-    /* update the total size of the screen and the size of each backdrop */
-    screen_size_changed_cb(gscreen, desktop);
+    /* create the new workspace and set it up */
+    desktop->priv->workspaces[nlast_workspace] = xfce_workspace_new(desktop->priv->gscreen,
+                                                                    desktop->priv->channel,
+                                                                    desktop->priv->property_prefix,
+                                                                    nlast_workspace);
+
+    xfce_workspace_monitors_changed(desktop->priv->workspaces[nlast_workspace],
+                                    desktop->priv->gscreen);
+
+    g_signal_connect(desktop->priv->workspaces[nlast_workspace],
+                     "workspace-backdrop-changed",
+                     G_CALLBACK(workspace_backdrop_changed_cb), desktop);
+}
+
+static void
+workspace_destroyed_cb(WnckScreen *wnck_screen,
+                     WnckWorkspace *old_workspace,
+                     gpointer user_data)
+{
+    XfceDesktop *desktop = XFCE_DESKTOP(user_data);
+    gint nlast_workspace;
+    TRACE("entering");
+
+    g_return_if_fail(XFCE_IS_DESKTOP(desktop));
+    g_return_if_fail(desktop->priv->nworkspaces - 1 >= 0);
+    g_return_if_fail(XFCE_IS_WORKSPACE(desktop->priv->workspaces[desktop->priv->nworkspaces-1]));
+
+    nlast_workspace = desktop->priv->nworkspaces - 1;
+
+    g_signal_handlers_disconnect_by_func(desktop->priv->workspaces[nlast_workspace],
+                                         G_CALLBACK(workspace_backdrop_changed_cb),
+                                         desktop);
+
+    g_object_unref(desktop->priv->workspaces[nlast_workspace]);
+
+    /* Remove one workspace */
+    desktop->priv->nworkspaces = nlast_workspace;
+
+    /* deallocate it */
+    desktop->priv->workspaces = g_realloc(desktop->priv->workspaces,
+                                          desktop->priv->nworkspaces * sizeof(XfceWorkspace *));
 }
 
 static void
@@ -621,13 +653,6 @@ xfce_desktop_class_init(XfceDesktopClass *klass)
                                 | G_PARAM_STATIC_NICK \
                                 | G_PARAM_STATIC_BLURB)
 
-    g_object_class_install_property(gobject_class, PROP_XINERAMA_STRETCH,
-                                    g_param_spec_boolean("xinerama-stretch",
-                                                         "xinerama stretch",
-                                                         "xinerama stretch",
-                                                         FALSE,
-                                                         XFDESKTOP_PARAM_FLAGS));
-
 #ifdef ENABLE_DESKTOP_ICONS
     g_object_class_install_property(gobject_class, PROP_ICON_STYLE,
                                     g_param_spec_enum("icon-style",
@@ -696,11 +721,6 @@ xfce_desktop_set_property(GObject *object,
     XfceDesktop *desktop = XFCE_DESKTOP(object);
 
     switch(property_id) {
-        case PROP_XINERAMA_STRETCH:
-            xfce_desktop_set_xinerama_stretch(desktop,
-                                              g_value_get_boolean(value));
-            break;
-
 #ifdef ENABLE_DESKTOP_ICONS
         case PROP_ICON_STYLE:
             xfce_desktop_set_icon_style(desktop,
@@ -738,10 +758,6 @@ xfce_desktop_get_property(GObject *object,
     XfceDesktop *desktop = XFCE_DESKTOP(object);
 
     switch(property_id) {
-        case PROP_XINERAMA_STRETCH:
-            g_value_set_boolean(value, desktop->priv->xinerama_stretch);
-            break;
-
 #ifdef ENABLE_DESKTOP_ICONS
         case PROP_ICON_STYLE:
             g_value_set_enum(value, desktop->priv->icons_style);
@@ -771,9 +787,11 @@ xfce_desktop_realize(GtkWidget *widget)
 {
     XfceDesktop *desktop = XFCE_DESKTOP(widget);
     GdkAtom atom;
-    gint sw, sh;
+    gint sw, sh, i;
     Window xid;
     GdkWindow *groot;
+    WnckScreen *wnck_screen;
+    WnckWorkspace *wnck_workspace;
     
     TRACE("entering");
 
@@ -818,13 +836,45 @@ xfce_desktop_realize(GtkWidget *widget)
     
     screen_set_selection(desktop);
 
+    /* We have to force wnck to initialize */
+    wnck_screen = wnck_screen_get(gdk_screen_get_number(desktop->priv->gscreen));
+    wnck_screen_force_update(wnck_screen);
+    desktop->priv->wnck_screen = wnck_screen;
+
+    /* 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->nworkspaces = wnck_screen_get_workspace_count(wnck_screen);
+
+    desktop->priv->workspaces = g_realloc(desktop->priv->workspaces,
+                                          desktop->priv->nworkspaces * sizeof(XfceWorkspace *));
+
+    for(i = 0; i < desktop->priv->nworkspaces; i++) {
+        desktop->priv->workspaces[i] = xfce_workspace_new(desktop->priv->gscreen,
+                                                          desktop->priv->channel,
+                                                          desktop->priv->property_prefix,
+                                                          i);
+        xfce_workspace_monitors_changed(desktop->priv->workspaces[i],
+                                        desktop->priv->gscreen);
+
+        g_signal_connect(desktop->priv->workspaces[i], "workspace-backdrop-changed",
+                         G_CALLBACK(workspace_backdrop_changed_cb), desktop);
+    }
+
+    g_signal_connect(desktop->priv->wnck_screen, "active-workspace-changed",
+                     G_CALLBACK(workspace_changed_cb), desktop);
+    g_signal_connect(desktop->priv->wnck_screen, "workspace-created",
+                     G_CALLBACK(workspace_created_cb), desktop);
+    g_signal_connect(desktop->priv->wnck_screen, "workspace-destroyed",
+                     G_CALLBACK(workspace_destroyed_cb), desktop);
+
     xfce_desktop_monitors_changed(desktop->priv->gscreen, desktop);
     
     g_signal_connect(G_OBJECT(desktop->priv->gscreen), "size-changed",
             G_CALLBACK(screen_size_changed_cb), desktop);
     g_signal_connect(G_OBJECT(desktop->priv->gscreen), "composited-changed",
             G_CALLBACK(screen_composited_changed_cb), desktop);
-    
+
     gtk_widget_add_events(GTK_WIDGET(desktop), GDK_EXPOSURE_MASK);
     
 #ifdef ENABLE_DESKTOP_ICONS
@@ -838,7 +888,7 @@ static void
 xfce_desktop_unrealize(GtkWidget *widget)
 {
     XfceDesktop *desktop = XFCE_DESKTOP(widget);
-    guint i;
+    gint i;
     GdkWindow *groot;
     gchar property_name[128];
     
@@ -877,14 +927,14 @@ xfce_desktop_unrealize(GtkWidget *widget)
     gdk_window_set_back_pixmap(groot, NULL, FALSE);
 #endif
 
-    if(desktop->priv->backdrops) {
-        for(i = 0; i < desktop->priv->nbackdrops; i++) {
+    if(desktop->priv->workspaces) {
+        for(i = 0; i < desktop->priv->nworkspaces; i++) {
             g_snprintf(property_name, 128, XFDESKTOP_IMAGE_FILE_FMT, i);
             gdk_property_delete(groot, gdk_atom_intern(property_name, FALSE));
-            g_object_unref(G_OBJECT(desktop->priv->backdrops[i]));
+            g_object_unref(G_OBJECT(desktop->priv->workspaces[i]));
         }
-        g_free(desktop->priv->backdrops);
-        desktop->priv->backdrops = NULL;
+        g_free(desktop->priv->workspaces);
+        desktop->priv->workspaces = NULL;
     }
 
     gdk_flush();
@@ -1016,15 +1066,9 @@ static void
 xfce_desktop_connect_settings(XfceDesktop *desktop)
 {
     XfconfChannel *channel = desktop->priv->channel;
-    gchar buf[1024];
 
     xfce_desktop_freeze_updates(desktop);
 
-    g_strlcpy(buf, desktop->priv->property_prefix, sizeof(buf));
-    g_strlcat(buf, "xinerama-stretch", sizeof(buf));
-    xfconf_g_property_bind(channel, buf, G_TYPE_BOOLEAN,
-                           G_OBJECT(desktop), "xinerama-stretch");
-
 #ifdef ENABLE_DESKTOP_ICONS
 #define ICONS_PREFIX "/desktop-icons/"
 
@@ -1053,131 +1097,44 @@ xfce_desktop_image_filename_changed(XfconfChannel *channel,
     XfceDesktop *desktop = user_data;
     gchar *p;
     const gchar *filename;
-    gint monitor;
+    gint monitor, current_workspace;
     XfceBackdrop *backdrop;
 
+    TRACE("entering");
+
     p = strstr(property, "/monitor");
     if(!p)
         return;
 
     monitor = atoi(p + 8);
-    if(monitor < 0 || monitor >= gdk_screen_get_n_monitors(desktop->priv->gscreen))
+    if(monitor < 0 || monitor >= xfce_desktop_get_n_monitors(desktop))
         return;
 
-    if(desktop->priv->xinerama_stretch && monitor != 0)
+    current_workspace = desktop->priv->current_workspace;
+
+    if(xfce_workspace_get_xinerama_stretch(desktop->priv->workspaces[current_workspace])
+       && monitor != 0)
         return;
-    backdrop = desktop->priv->backdrops[monitor];
+
+    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)) {
-        if(xfdesktop_backdrop_list_is_valid(filename)) {
-            gchar *backdrop_file;
-            GError *error = NULL;
-            
-            backdrop_file = xfdesktop_backdrop_list_choose_random(filename,
-                                                                  &error);
-#if 0
-            if(!backdrop_file && !xfdesktop_backdrop_list_is_valid(filename)) {
-                gchar *primary = g_strdup_printf(_("Unable to load image from backdrop list file \"%s\""),
-                                                 filename);
-                xfce_message_dialog(GTK_WINDOW(desktop), _("Desktop Error"),
-                                    GTK_STOCK_DIALOG_ERROR, primary,
-                                    error->message,
-                                    GTK_STOCK_CLOSE, GTK_RESPONSE_ACCEPT,
-                                    NULL);
-                g_error_free(error);
-                g_free(primary);
-            }
-#endif
-
-            xfce_backdrop_set_image_filename(backdrop, backdrop_file);
-            g_free(backdrop_file);
 
-            xfce_backdrop_set_list(backdrop, g_strdup(filename));
-        } else {
-            xfce_backdrop_set_image_filename(backdrop, filename);
-
-            xfce_backdrop_set_list(backdrop, NULL);
-        }
-    }
+    if(G_LIKELY(filename && *filename))
+        xfce_backdrop_set_image_filename(backdrop, filename);
 }
 
-static void
-xfce_desktop_connect_backdrop_settings(XfceDesktop *desktop,
-                                       XfceBackdrop *backdrop,
-                                       guint monitor)
+static gint
+xfce_desktop_get_current_workspace(XfceDesktop *desktop)
 {
-    XfconfChannel *channel = desktop->priv->channel;
-    char buf[1024], buf1[1024];
-    gint pp_len;
-    GValue value = { 0, };
-
-    g_snprintf(buf, sizeof(buf), "%smonitor%d/",
-               desktop->priv->property_prefix, monitor);
-    pp_len = strlen(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");
-
-    buf[pp_len] = 0;
-    g_strlcat(buf, "color2", sizeof(buf));
-    xfconf_g_property_bind_gdkcolor(channel, buf,
-                                    G_OBJECT(backdrop), "second-color");
-
-    buf[pp_len] = 0;
-    g_strlcat(buf, "image-show", sizeof(buf));
-    xfconf_g_property_bind(channel, buf, G_TYPE_BOOLEAN,
-                           G_OBJECT(backdrop), "show-image");
-
-    buf[pp_len] = 0;
-    g_strlcat(buf, "image-style", sizeof(buf));
-    xfconf_g_property_bind(channel, buf, XFCE_TYPE_BACKDROP_IMAGE_STYLE,
-                           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, "saturation", sizeof(buf));
-    xfconf_g_property_bind(channel, buf, G_TYPE_DOUBLE,
-                           G_OBJECT(backdrop), "saturation");
-
-    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");
-
-    buf[pp_len] = 0;
-    g_strlcat(buf, "backdrop-cycle-timer", sizeof(buf));
-    xfconf_g_property_bind(channel, buf, G_TYPE_UINT,
-                           G_OBJECT(backdrop), "backdrop-cycle-timer");
-
-    /* the image filename could be an image or a backdrop list, so we
-     * can't just bind the property directly */
-    buf[pp_len] = 0;
-    g_strlcat(buf, "image-path", sizeof(buf));
-    g_strlcpy(buf1, "property-changed::", sizeof(buf1));
-    g_strlcat(buf1, buf, sizeof(buf1));
-    g_signal_connect(G_OBJECT(channel), buf1,
-                     G_CALLBACK(xfce_desktop_image_filename_changed), desktop);
-    if(xfconf_channel_get_property(channel, buf, &value)) {
-        xfce_desktop_image_filename_changed(channel, buf, &value, desktop);
-        g_value_unset(&value);
-    }
-}
-
+    g_return_val_if_fail(XFCE_IS_DESKTOP(desktop), -1);
 
+    return desktop->priv->current_workspace;
+}
 
 /* public api */
 
@@ -1216,12 +1173,12 @@ xfce_desktop_new(GdkScreen *gscreen,
     return GTK_WIDGET(desktop);
 }
 
-guint
+gint
 xfce_desktop_get_n_monitors(XfceDesktop *desktop)
 {
     g_return_val_if_fail(XFCE_IS_DESKTOP(desktop), 0);
     
-    return desktop->priv->nbackdrops;
+    return gdk_screen_get_n_monitors(desktop->priv->gscreen);
 }
 
 gint
@@ -1241,28 +1198,6 @@ xfce_desktop_get_height(XfceDesktop *desktop)
 }
 
 void
-xfce_desktop_set_xinerama_stretch(XfceDesktop *desktop,
-                                  gboolean stretch)
-{
-    g_return_if_fail(XFCE_IS_DESKTOP(desktop));
-    
-    if(stretch == desktop->priv->xinerama_stretch)
-        return;
-    
-    desktop->priv->xinerama_stretch = stretch;
-    
-    if(!desktop->priv->updates_frozen)
-        xfce_desktop_monitors_changed(desktop->priv->gscreen, desktop);
-}
-
-gboolean
-xfce_desktop_get_xinerama_stretch(XfceDesktop *desktop)
-{
-    g_return_val_if_fail(XFCE_IS_DESKTOP(desktop), FALSE);
-    return desktop->priv->xinerama_stretch;
-}
-
-void
 xfce_desktop_set_icon_style(XfceDesktop *desktop,
                             XfceDesktopIconStyle style)
 {
@@ -1384,16 +1319,6 @@ xfce_desktop_thaw_updates(XfceDesktop *desktop)
         xfce_desktop_monitors_changed(desktop->priv->gscreen, desktop);
 }
 
-XfceBackdrop *
-xfce_desktop_peek_backdrop(XfceDesktop *desktop,
-                           guint monitor)
-{
-    g_return_val_if_fail(XFCE_IS_DESKTOP(desktop)
-                         && gtk_widget_get_realized(GTK_WIDGET(desktop))
-                         && monitor < desktop->priv->nbackdrops, NULL);
-    return desktop->priv->backdrops[monitor];
-}
-
 static gboolean
 xfce_desktop_menu_destroy_idled(gpointer data)
 {
@@ -1470,23 +1395,25 @@ void
 xfce_desktop_refresh(XfceDesktop *desktop)
 {
     gchar buf[256];
-    guint i, max;
+    gint i, max, 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(desktop->priv->xinerama_stretch)
+    if(xfce_workspace_get_xinerama_stretch(desktop->priv->workspaces[current_workspace]))
         max = 1;
     else
-        max = desktop->priv->nbackdrops;
+        max = xfce_desktop_get_n_monitors(desktop);
     for(i = 0; i < max; ++i) {
         GValue val = { 0, };
 
-        g_snprintf(buf, sizeof(buf), "%smonitor%d/image-path",
-                   desktop->priv->property_prefix, i);
+        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);
 
         xfce_desktop_image_filename_changed(desktop->priv->channel, buf,
diff --git a/src/xfce-desktop.h b/src/xfce-desktop.h
index a9224af..ade6aeb 100644
--- a/src/xfce-desktop.h
+++ b/src/xfce-desktop.h
@@ -77,15 +77,11 @@ GtkWidget *xfce_desktop_new(GdkScreen *gscreen,
                             XfconfChannel *channel,
                             const gchar *property_prefix);
 
-guint xfce_desktop_get_n_monitors(XfceDesktop *desktop);
+gint xfce_desktop_get_n_monitors(XfceDesktop *desktop);
 
 gint xfce_desktop_get_width(XfceDesktop *desktop);
 gint xfce_desktop_get_height(XfceDesktop *desktop);
 
-void xfce_desktop_set_xinerama_stretch(XfceDesktop *desktop,
-                                       gboolean stretch);
-gboolean xfce_desktop_get_xinerama_stretch(XfceDesktop *desktop);
-
 void xfce_desktop_set_icon_style(XfceDesktop *desktop,
                                  XfceDesktopIconStyle style);
 XfceDesktopIconStyle xfce_desktop_get_icon_style(XfceDesktop *desktop);
@@ -104,8 +100,6 @@ void xfce_desktop_set_session_logout_func(XfceDesktop *desktop,
 void xfce_desktop_freeze_updates(XfceDesktop *desktop);
 void xfce_desktop_thaw_updates(XfceDesktop *desktop);
 
-XfceBackdrop *xfce_desktop_peek_backdrop(XfceDesktop *desktop,
-                                         guint monitor);
 
 void xfce_desktop_popup_root_menu(XfceDesktop *desktop,
                                   guint button,
diff --git a/src/xfce-workspace.c b/src/xfce-workspace.c
new file mode 100644
index 0000000..ba9f327
--- /dev/null
+++ b/src/xfce-workspace.c
@@ -0,0 +1,432 @@
+/*
+ *  xfworkspace - xfce4's desktop manager
+ *
+ *  Copyright (c) 2004-2007 Brian Tarricone, <bjt23 at cornell.edu>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *  Random portions taken from or inspired by the original xfworkspace for xfce4:
+ *     Copyright (C) 2002-2003 Jasper Huijsmans (huysmans at users.sourceforge.net)
+ *     Copyright (C) 2003 Benedikt Meurer <benedikt.meurer at unix-ag.uni-siegen.de>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#include <ctype.h>
+#include <errno.h>
+
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+
+#include <glib.h>
+#include <gdk/gdkx.h>
+#include <gtk/gtk.h>
+
+#include <libxfce4util/libxfce4util.h>
+#include <libxfce4ui/libxfce4ui.h>
+
+#include <xfconf/xfconf.h>
+
+#include "xfdesktop-common.h"
+#include "xfce-workspace.h"
+#include "xfce-desktop-enum-types.h"
+
+struct _XfceWorkspacePriv
+{
+    GdkScreen *gscreen;
+
+    XfconfChannel *channel;
+    gchar *property_prefix;
+
+    guint workspace_num;
+    guint nbackdrops;
+    XfceBackdrop **backdrops;
+};
+
+enum
+{
+    WORKSPACE_BACKDROP_CHANGED,
+    N_SIGNALS,
+};
+
+static guint signals[N_SIGNALS] = { 0, };
+
+static void xfce_workspace_finalize(GObject *object);
+static void xfce_workspace_set_property(GObject *object,
+                                      guint property_id,
+                                      const GValue *value,
+                                      GParamSpec *pspec);
+static void xfce_workspace_get_property(GObject *object,
+                                      guint property_id,
+                                      GValue *value,
+                                      GParamSpec *pspec);
+
+static void xfce_workspace_connect_backdrop_settings(XfceWorkspace *workspace,
+                                                   XfceBackdrop *backdrop,
+                                                   guint monitor);
+
+G_DEFINE_TYPE(XfceWorkspace, xfce_workspace, G_TYPE_OBJECT)
+
+gboolean
+xfce_workspace_get_xinerama_stretch(XfceWorkspace *workspace)
+{
+    g_return_val_if_fail(XFCE_IS_WORKSPACE(workspace), FALSE);
+    g_return_val_if_fail(workspace->priv->backdrops != NULL, FALSE);
+    g_return_val_if_fail(XFCE_IS_BACKDROP(workspace->priv->backdrops[0]), FALSE);
+
+    return xfce_backdrop_get_image_style(workspace->priv->backdrops[0]) == XFCE_BACKDROP_IMAGE_SPANNING_SCREENS;
+}
+
+static void
+backdrop_cycle_cb(XfceBackdrop *backdrop, gpointer user_data)
+{
+    const gchar* backdrop_file;
+    gchar *new_backdrop = NULL;
+    XfceWorkspace *workspace = XFCE_WORKSPACE(user_data);
+
+    TRACE("entering");
+
+    g_return_if_fail(XFCE_IS_BACKDROP(backdrop));
+
+    backdrop_file = xfce_backdrop_get_image_filename(backdrop);
+
+    if(backdrop_file == NULL)
+        return;
+
+    if(xfce_backdrop_get_random_order(backdrop)) {
+        DBG("Random! current file: %s", backdrop_file);
+        new_backdrop = xfdesktop_backdrop_choose_random(backdrop_file);
+    } else {
+        DBG("Next! current file: %s", backdrop_file);
+        new_backdrop = xfdesktop_backdrop_choose_next(backdrop_file);
+    }
+    DBG("new file: %s for Workspace %d", new_backdrop,
+        xfce_workspace_get_workspace_num(workspace));
+
+    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)
+{
+    TRACE("entering");
+    /* Propagate it up */
+    g_signal_emit(G_OBJECT(user_data), signals[WORKSPACE_BACKDROP_CHANGED], 0, backdrop);
+}
+
+void
+xfce_workspace_monitors_changed(XfceWorkspace *workspace,
+                                GdkScreen *gscreen)
+{
+    guint i;
+
+    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]));
+        }
+
+        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;
+        }
+    } 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]));
+        }
+
+        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;
+        }
+    }
+}
+
+static void
+xfce_workspace_class_init(XfceWorkspaceClass *klass)
+{
+    GObjectClass *gobject_class = (GObjectClass *)klass;
+
+    g_type_class_add_private(klass, sizeof(XfceWorkspacePriv));
+
+    gobject_class->finalize = xfce_workspace_finalize;
+    gobject_class->set_property = xfce_workspace_set_property;
+    gobject_class->get_property = xfce_workspace_get_property;
+
+    signals[WORKSPACE_BACKDROP_CHANGED] = g_signal_new("workspace-backdrop-changed",
+                                                   XFCE_TYPE_WORKSPACE,
+                                                   G_SIGNAL_RUN_LAST,
+                                                   G_STRUCT_OFFSET(XfceWorkspaceClass,
+                                                                   changed),
+                                                   NULL, NULL,
+                                                   g_cclosure_marshal_VOID__POINTER,
+                                                   G_TYPE_NONE, 1,
+                                                   G_TYPE_POINTER);
+}
+
+static void
+xfce_workspace_init(XfceWorkspace *workspace)
+{
+    workspace->priv = G_TYPE_INSTANCE_GET_PRIVATE(workspace, XFCE_TYPE_WORKSPACE,
+                                                XfceWorkspacePriv);
+}
+
+static void
+xfce_workspace_finalize(GObject *object)
+{
+    XfceWorkspace *workspace = XFCE_WORKSPACE(object);
+
+    g_object_unref(G_OBJECT(workspace->priv->channel));
+    g_free(workspace->priv->property_prefix);
+
+}
+
+static void
+xfce_workspace_set_property(GObject *object,
+                          guint property_id,
+                          const GValue *value,
+                          GParamSpec *pspec)
+{
+    switch(property_id) {
+        default:
+            G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
+            break;
+    }
+}
+
+static void
+xfce_workspace_get_property(GObject *object,
+                          guint property_id,
+                          GValue *value,
+                          GParamSpec *pspec)
+{
+    switch(property_id) {
+        default:
+            G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
+            break;
+    }
+}
+
+static void
+xfce_workspace_connect_backdrop_settings(XfceWorkspace *workspace,
+                                         XfceBackdrop *backdrop,
+                                         guint monitor)
+{
+    XfconfChannel *channel = workspace->priv->channel;
+    char buf[1024];
+    gint pp_len;
+    gchar *monitor_name = NULL;
+
+    TRACE("entering");
+
+    monitor_name = gdk_screen_get_monitor_plug_name(workspace->priv->gscreen, monitor);
+
+    if(monitor_name == NULL) {
+        g_snprintf(buf, sizeof(buf), "%smonitor%d/workspace%d/",
+                   workspace->priv->property_prefix, monitor, workspace->priv->workspace_num);
+    } else {
+        g_snprintf(buf, sizeof(buf), "%smonitor%s/workspace%d/",
+                   workspace->priv->property_prefix, monitor_name, workspace->priv->workspace_num);
+    }
+    pp_len = strlen(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");
+
+    buf[pp_len] = 0;
+    g_strlcat(buf, "color2", sizeof(buf));
+    xfconf_g_property_bind_gdkcolor(channel, buf,
+                                    G_OBJECT(backdrop), "second-color");
+
+    buf[pp_len] = 0;
+    g_strlcat(buf, "image-style", sizeof(buf));
+    xfconf_g_property_bind(channel, buf, XFCE_TYPE_BACKDROP_IMAGE_STYLE,
+                           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");
+
+    buf[pp_len] = 0;
+    g_strlcat(buf, "backdrop-cycle-timer", sizeof(buf));
+    xfconf_g_property_bind(channel, buf, G_TYPE_UINT,
+                           G_OBJECT(backdrop), "backdrop-cycle-timer");
+
+    buf[pp_len] = 0;
+    g_strlcat(buf, "backdrop-cycle-random-order", sizeof(buf));
+    xfconf_g_property_bind(channel, buf, G_TYPE_BOOLEAN,
+                           G_OBJECT(backdrop), "backdrop-cycle-random-order");
+
+    buf[pp_len] = 0;
+    g_strlcat(buf, "last-image", sizeof(buf));
+    xfconf_g_property_bind(channel, buf, G_TYPE_STRING,
+                           G_OBJECT(backdrop), "image-filename");
+
+    g_free(monitor_name);
+}
+
+
+
+/* public api */
+
+/**
+ * xfce_workspace_new:
+ * @gscreen: The current #GdkScreen.
+ * @channel: An #XfconfChannel to use for settings.
+ * @property_prefix: String prefix for per-screen properties.
+ * @number: The workspace number to represent
+ *
+ * Creates a new #XfceWorkspace for the specified #GdkScreen.  If @gscreen is
+ * %NULL, the default screen will be used.
+ *
+ * Return value: A new #XfceWorkspace.
+ **/
+XfceWorkspace *
+xfce_workspace_new(GdkScreen *gscreen,
+                   XfconfChannel *channel,
+                   const gchar *property_prefix,
+                   gint number)
+{
+    XfceWorkspace *workspace;
+
+    g_return_val_if_fail(channel && property_prefix, NULL);
+
+    workspace = g_object_new(XFCE_TYPE_WORKSPACE, NULL);
+
+    if(!gscreen)
+        gscreen = gdk_display_get_default_screen(gdk_display_get_default());
+
+    workspace->priv->gscreen = gscreen;
+    workspace->priv->workspace_num = number;
+    workspace->priv->channel = g_object_ref(G_OBJECT(channel));
+    workspace->priv->property_prefix = g_strdup(property_prefix);
+
+    return workspace;
+}
+
+gint
+xfce_workspace_get_workspace_num(XfceWorkspace *workspace)
+{
+    g_return_val_if_fail(XFCE_IS_WORKSPACE(workspace), -1);
+
+    return workspace->priv->workspace_num;
+}
+
+void
+xfce_workspace_set_workspace_num(XfceWorkspace *workspace, gint number)
+{
+    g_return_if_fail(XFCE_IS_WORKSPACE(workspace));
+
+    workspace->priv->workspace_num = number;
+}
+
+XfceBackdrop *xfce_workspace_get_backdrop(XfceWorkspace *workspace,
+                                          guint monitor)
+{
+    g_return_val_if_fail(XFCE_IS_WORKSPACE(workspace)
+                         && monitor < workspace->priv->nbackdrops, NULL);
+    return workspace->priv->backdrops[monitor];
+}
diff --git a/src/xfce-workspace.h b/src/xfce-workspace.h
new file mode 100644
index 0000000..173bc15
--- /dev/null
+++ b/src/xfce-workspace.h
@@ -0,0 +1,78 @@
+/*
+ *  xfworkspace - xfce4's desktop manager
+ *
+ *  Copyright (c) 2004-2007 Brian Tarricone, <bjt23 at cornell.edu>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _XFCE_WORKSPACE_H_
+#define _XFCE_WORKSPACE_H_
+
+#include <gtk/gtk.h>
+#include <xfconf/xfconf.h>
+
+#include "xfce-backdrop.h"
+
+G_BEGIN_DECLS
+
+#define XFCE_TYPE_WORKSPACE              (xfce_workspace_get_type())
+#define XFCE_WORKSPACE(object)           (G_TYPE_CHECK_INSTANCE_CAST((object), XFCE_TYPE_WORKSPACE, XfceWorkspace))
+#define XFCE_WORKSPACE_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST((klass), XFCE_TYPE_WORKSPACE, XfceWorkspaceClass))
+#define XFCE_IS_WORKSPACE(object)        (G_TYPE_CHECK_INSTANCE_TYPE((object), XFCE_TYPE_WORKSPACE))
+#define XFCE_IS_WORKSPACE_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE((klass), XFCE_TYPE_WORKSPACE))
+#define XFCE_WORKSPACE_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS((object), XFCE_TYPE_WORKSPACE, XfceWorkspaceClass))
+
+typedef struct _XfceWorkspace XfceWorkspace;
+typedef struct _XfceWorkspaceClass XfceWorkspaceClass;
+typedef struct _XfceWorkspacePriv XfceWorkspacePriv;
+
+struct _XfceWorkspace
+{
+    GObject gobject;
+
+    /*< private >*/
+    XfceWorkspacePriv *priv;
+};
+
+struct _XfceWorkspaceClass
+{
+    GObjectClass parent_class;
+
+    /*< signals >*/
+    void (*changed)(XfceWorkspace *workspace, XfceBackdrop *backdrop);
+};
+
+GType xfce_workspace_get_type                     (void) G_GNUC_CONST;
+
+XfceWorkspace *xfce_workspace_new(GdkScreen *gscreen,
+                                  XfconfChannel *channel,
+                                  const gchar *property_prefix,
+                                  gint number);
+
+gint xfce_workspace_get_workspace_num(XfceWorkspace *workspace);
+void xfce_workspace_set_workspace_num(XfceWorkspace *workspace, gint number);
+
+void xfce_workspace_monitors_changed(XfceWorkspace *workspace,
+                                     GdkScreen *gscreen);
+
+gboolean xfce_workspace_get_xinerama_stretch(XfceWorkspace *workspace);
+
+XfceBackdrop *xfce_workspace_get_backdrop(XfceWorkspace *workspace,
+                                          guint monitor);
+
+G_END_DECLS
+
+#endif


More information about the Xfce4-commits mailing list