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