diff options
-rw-r--r-- | common/xfdesktop-common.c | 15 | ||||
-rw-r--r-- | common/xfdesktop-common.h | 2 | ||||
-rw-r--r-- | settings/main.c | 401 | ||||
-rw-r--r-- | settings/xfce-backdrop-settings.desktop.in | 2 | ||||
-rw-r--r-- | src/xfce-backdrop.c | 83 | ||||
-rw-r--r-- | src/xfce-backdrop.h | 2 | ||||
-rw-r--r-- | src/xfce-desktop.c | 23 | ||||
-rw-r--r-- | src/xfce-workspace.c | 155 |
8 files changed, 553 insertions, 130 deletions
diff --git a/common/xfdesktop-common.c b/common/xfdesktop-common.c index 65f02142..b2fb406f 100644 --- a/common/xfdesktop-common.c +++ b/common/xfdesktop-common.c @@ -51,6 +51,7 @@ #include <libxfce4util/libxfce4util.h> #include "xfdesktop-common.h" +#include "xfce-backdrop.h" /* for XfceBackdropImageStyle */ #ifndef O_BINARY #define O_BINARY 0 @@ -301,6 +302,20 @@ xfdesktop_send_client_message(Window xid, const gchar *msg) gtk_widget_destroy(win); } +/* The image styles changed from versions prior to 4.11. + * Auto isn't an option anymore, additionally we should handle invalid + * values. Set them to the default of stretched. */ +gint +xfce_translate_image_styles(gint input) +{ + gint style = input; + + if(style <= 0 || style > XFCE_BACKDROP_IMAGE_SPANNING_SCREENS) + style = XFCE_BACKDROP_IMAGE_STRETCHED; + + return style; +} + guint xfce_grab_cursor(GtkWidget *w, GdkEventButton *evt) diff --git a/common/xfdesktop-common.h b/common/xfdesktop-common.h index 1d6db855..725da4fa 100644 --- a/common/xfdesktop-common.h +++ b/common/xfdesktop-common.h @@ -86,6 +86,8 @@ 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); +gint xfce_translate_image_styles(gint input); + guint xfce_grab_cursor(GtkWidget *w, GdkEventButton *evt); gboolean xfdesktop_popup_grab_available(GdkWindow *win, guint32 timestamp); diff --git a/settings/main.c b/settings/main.c index 69a5da5b..74da46e4 100644 --- a/settings/main.c +++ b/settings/main.c @@ -48,14 +48,19 @@ #include <xfconf/xfconf.h> #include <libxfce4ui/libxfce4ui.h> #include <libwnck/libwnck.h> +#include <exo/exo.h> #include "xfdesktop-common.h" #include "xfdesktop-thumbnailer.h" #include "xfdesktop-settings-ui.h" #include "xfdesktop-settings-appearance-frame-ui.h" +/* for XfceBackdropImageStyle && XfceBackdropColorStyle */ +#include "xfce-backdrop.h" -#define PREVIEW_HEIGHT 96 #define MAX_ASPECT_RATIO 1.5f +#define PREVIEW_HEIGHT 96 +#define PREVIEW_WIDTH (PREVIEW_HEIGHT * MAX_ASPECT_RATIO) + #define SHOW_DESKTOP_MENU_PROP "/desktop-menu/show" #define DESKTOP_MENU_SHOW_ICONS_PROP "/desktop-menu/show-icons" @@ -77,9 +82,6 @@ #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 { @@ -97,6 +99,9 @@ typedef struct gulong image_list_loaded:1; WnckWindow *wnck_window; + /* We keep track of the current workspace number because + * wnck_screen_get_active_workspace sometimes has to return NULL. */ + gint active_workspace; GtkWidget *frame_image_list; GtkWidget *image_iconview; @@ -158,58 +163,41 @@ 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); - +static gchar *xfdesktop_settings_get_backdrop_image(AppearancePanel *panel); static void xfdesktop_settings_do_single_preview(GtkTreeModel *model, GtkTreeIter *iter) { gchar *filename = NULL, *thumbnail = NULL; - GdkPixbuf *pix, *pix_scaled = NULL; + GdkPixbuf *pix; - GDK_THREADS_ENTER (); gtk_tree_model_get(model, iter, COL_FILENAME, &filename, COL_THUMBNAIL, &thumbnail, -1); - GDK_THREADS_LEAVE (); + /* If we didn't create a thumbnail there might not be a thumbnailer service + * or it may not support that format */ if(thumbnail == NULL) { - pix = gdk_pixbuf_new_from_file(filename, NULL); + pix = exo_gdk_pixbuf_new_from_file_at_max_size(filename, + PREVIEW_WIDTH, PREVIEW_HEIGHT, + TRUE, NULL); } else { - pix = gdk_pixbuf_new_from_file(thumbnail, NULL); + pix = exo_gdk_pixbuf_new_from_file_at_max_size(thumbnail, + PREVIEW_WIDTH, PREVIEW_HEIGHT, + TRUE, NULL); g_free(thumbnail); } g_free(filename); - if(pix) { - gint width, height; - gdouble aspect; - width = gdk_pixbuf_get_width(pix); - height = gdk_pixbuf_get_height(pix); - aspect = (gdouble)width / height; - - /* Keep the aspect ratio sensible otherwise the treeview looks bad */ - if(aspect > MAX_ASPECT_RATIO) { - aspect = MAX_ASPECT_RATIO; - } - - width = PREVIEW_HEIGHT * aspect; - height = PREVIEW_HEIGHT; - pix_scaled = gdk_pixbuf_scale_simple(pix, width, height, - GDK_INTERP_BILINEAR); - - g_object_unref(G_OBJECT(pix)); - } - - if(pix_scaled) { - GDK_THREADS_ENTER (); + if(pix) { gtk_list_store_set(GTK_LIST_STORE(model), iter, - COL_PIX, pix_scaled, + COL_PIX, pix, -1); - GDK_THREADS_LEAVE (); - g_object_unref(G_OBJECT(pix_scaled)); + + g_object_unref(G_OBJECT(pix)); } } @@ -259,7 +247,7 @@ xfdesktop_settings_add_file_to_queue(AppearancePanel *panel, PreviewData *pdata) /* Create the thread if it doesn't exist */ if(panel->preview_thread == NULL) { #if GLIB_CHECK_VERSION(2, 32, 0) - panel->preview_thread = g_thread_try_new("xfdesktop_settings_create_previews", + panel->preview_thread = g_thread_try_new("create_previews", xfdesktop_settings_create_previews, panel, NULL); #else @@ -615,7 +603,6 @@ xfdesktop_image_list_add_dir(GObject *source_object, gpointer user_data) { AppearancePanel *panel = user_data; - gchar *property; AddDirData *dir_data = g_new0(AddDirData, 1); TRACE("entering"); @@ -627,9 +614,7 @@ xfdesktop_image_list_add_dir(GObject *source_object, /* 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->last_image = xfdesktop_settings_get_backdrop_image(panel); dir_data->file_path = g_file_get_path(panel->selected_folder); @@ -643,8 +628,6 @@ xfdesktop_image_list_add_dir(GObject *source_object, xfdesktop_image_list_add_item, dir_data, cb_destroy_add_dir_enumeration); - - g_free(property); } static void @@ -653,16 +636,24 @@ xfdesktop_settings_update_iconview_frame_name(AppearancePanel *panel, { gchar buf[1024]; gchar *workspace_name; + WnckScreen *screen; + WnckWorkspace *workspace; - if(panel->monitor < 0 && panel->workspace < 0) + /* Don't update the name until we find our window */ + if(panel->wnck_window == NULL) return; + g_return_if_fail(panel->monitor >= 0 && panel->workspace >= 0); + + /* If it's a pinned window get the active workspace */ if(wnck_workspace == NULL) { - WnckScreen *wnck_screen = wnck_window_get_screen(panel->wnck_window); - wnck_workspace = wnck_screen_get_active_workspace(wnck_screen); + screen = wnck_window_get_screen(panel->wnck_window); + workspace = wnck_screen_get_workspace(screen, panel->active_workspace); + } else { + workspace = wnck_workspace; } - workspace_name = g_strdup(wnck_workspace_get_name(wnck_workspace)); + workspace_name = g_strdup(wnck_workspace_get_name(workspace)); 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))) { @@ -723,6 +714,51 @@ xfdesktop_settings_generate_per_workspace_binding_string(AppearancePanel *panel, return buf; } +static gchar* +xfdesktop_settings_generate_old_binding_string(AppearancePanel *panel, + const gchar* property) +{ + gchar *buf = NULL; + + buf = g_strdup_printf("/backdrop/screen%d/monitor%d/%s", + panel->screen, panel->monitor, property); + + DBG("name %s", buf); + + return buf; +} + +/* Attempts to load the backdrop from the current location followed by using + * how previous versions of xfdesktop (before 4.11) did. This matches how + * xfdesktop searches for backdrops. + * Free the returned string when done using it. */ +static gchar * +xfdesktop_settings_get_backdrop_image(AppearancePanel *panel) +{ + gchar *last_image; + gchar *property, *old_property = NULL; + + /* Get the last image/current image displayed, if available */ + property = xfdesktop_settings_generate_per_workspace_binding_string(panel, "last-image"); + + last_image = xfconf_channel_get_string(panel->channel, property, NULL); + + /* Try the previous version or fall back to our provided default */ + if(last_image == NULL) { + old_property = xfdesktop_settings_generate_old_binding_string(panel, + "image-path"); + last_image = xfconf_channel_get_string(panel->channel, + old_property, + DEFAULT_BACKDROP); + } + + g_free(property); + if(old_property) + g_free(old_property); + + return last_image; +} + static void cb_image_selection_changed(GtkIconView *icon_view, gpointer user_data) @@ -732,7 +768,7 @@ cb_image_selection_changed(GtkIconView *icon_view, GtkTreeIter iter; GList *selected_items = NULL; gchar *filename = NULL, *current_filename = NULL; - gchar *buf; + gchar *buf = NULL; TRACE("entering"); @@ -751,9 +787,8 @@ cb_image_selection_changed(GtkIconView *icon_view, gtk_tree_model_get(model, &iter, COL_FILENAME, &filename, -1); - buf = xfdesktop_settings_generate_per_workspace_binding_string(panel, "last-image"); - - current_filename = xfconf_channel_get_string(panel->channel, buf, ""); + /* Get the current/last image, handles migrating from old versions */ + current_filename = xfdesktop_settings_get_backdrop_image(panel); /* check to see if the selection actually did change */ if(g_strcmp0(current_filename, filename) != 0) { @@ -765,13 +800,19 @@ cb_image_selection_changed(GtkIconView *icon_view, panel->screen, panel->monitor_name, panel->workspace); } + /* Get the property location to save our changes, always save to new + * location */ + buf = xfdesktop_settings_generate_per_workspace_binding_string(panel, + "last-image"); + DBG("Saving to %s/%s", buf, filename); 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); + if(buf) + g_free(buf); } static gint @@ -785,13 +826,14 @@ xfdesktop_settings_get_active_workspace(AppearancePanel *panel, wnck_workspace = wnck_window_get_workspace(wnck_window); + /* If wnck_workspace is NULL that means it's pinned and we just need to + * use the active/current workspace */ 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)); + workspace_num = panel->active_workspace; } - single_workspace = xfconf_channel_get_bool(panel->channel, SINGLE_WORKSPACE_MODE, TRUE); @@ -1033,12 +1075,15 @@ cb_xfdesktop_combo_color_changed(GtkComboBox *combo, static void xfdesktop_settings_update_iconview_folder(AppearancePanel *panel) { - gchar *current_folder, *prop_last, *dirname; + gchar *current_folder, *dirname; + + /* If we haven't found our window return now and wait for that */ + if(panel->wnck_window == NULL) + return; 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); + current_folder = xfdesktop_settings_get_backdrop_image(panel); dirname = g_path_get_dirname(current_folder); gtk_file_chooser_set_current_folder((GtkFileChooser*)panel->btn_folder, dirname); @@ -1047,7 +1092,6 @@ xfdesktop_settings_update_iconview_folder(AppearancePanel *panel) cb_folder_selection_changed(panel->btn_folder, panel); g_free(current_folder); - g_free(prop_last); g_free(dirname); } @@ -1057,15 +1101,30 @@ static void xfdesktop_settings_background_tab_change_bindings(AppearancePanel *panel, gboolean remove_binding) { - gchar *buf; + gchar *buf, *old_property = NULL; XfconfChannel *channel = panel->channel; - /* Style combobox */ + /* Image style combo box */ buf = xfdesktop_settings_generate_per_workspace_binding_string(panel, "image-style"); if(remove_binding) { xfconf_g_property_unbind_by_property(channel, buf, G_OBJECT(panel->image_style_combo), "active"); } else { + /* If the current image style doesn't exist, try to load the old one */ + if(!xfconf_channel_has_property(channel, buf)) { + gint image_style; + old_property = xfdesktop_settings_generate_old_binding_string(panel, "image-style"); + + /* default to stretched when trying to migrate */ + image_style = xfconf_channel_get_int(channel, old_property, XFCE_BACKDROP_IMAGE_STRETCHED); + + /* xfce_translate_image_styles will do sanity checking */ + gtk_combo_box_set_active(GTK_COMBO_BOX(panel->image_style_combo), + xfce_translate_image_styles(image_style)); + + g_free(old_property); + } + xfconf_g_property_bind(channel, buf, G_TYPE_INT, G_OBJECT(panel->image_style_combo), "active"); /* determine if the iconview is sensitive */ @@ -1073,12 +1132,31 @@ xfdesktop_settings_background_tab_change_bindings(AppearancePanel *panel, } g_free(buf); - /* Color options*/ + /* Color style combo box */ buf = xfdesktop_settings_generate_per_workspace_binding_string(panel, "color-style"); if(remove_binding) { xfconf_g_property_unbind_by_property(channel, buf, G_OBJECT(panel->color_style_combo), "active"); } else { + /* If the current color style doesn't exist, try to load the old one */ + if(!xfconf_channel_has_property(channel, buf)) { + gint color_style; + old_property = xfdesktop_settings_generate_old_binding_string(panel, "color-style"); + + /* default to solid when trying to migrate */ + color_style = xfconf_channel_get_int(channel, old_property, XFCE_BACKDROP_COLOR_SOLID); + + /* sanity check */ + if(color_style < 0 || color_style > XFCE_BACKDROP_COLOR_TRANSPARENT) { + g_warning("invalid color style, setting to solid"); + color_style = XFCE_BACKDROP_COLOR_SOLID; + } + + gtk_combo_box_set_active(GTK_COMBO_BOX(panel->color_style_combo), + color_style); + g_free(old_property); + } + xfconf_g_property_bind(channel, buf, G_TYPE_INT, G_OBJECT(panel->color_style_combo), "active"); /* update the color button sensitivity */ @@ -1086,27 +1164,63 @@ xfdesktop_settings_background_tab_change_bindings(AppearancePanel *panel, } g_free(buf); + /* color 1 button */ buf = xfdesktop_settings_generate_per_workspace_binding_string(panel, "color1"); if(remove_binding) { xfconf_g_property_unbind(panel->color1_btn_id); } else { + /* If the first color doesn't exist, try to load the old one */ + if(!xfconf_channel_has_property(channel, buf)) { + GValue value = { 0, }; + old_property = xfdesktop_settings_generate_old_binding_string(panel, "color1"); + + xfconf_channel_get_property(channel, old_property, &value); + + if(G_VALUE_HOLDS_BOXED(&value)) { + gtk_color_button_set_color(GTK_COLOR_BUTTON(panel->color1_btn), + g_value_get_boxed(&value)); + g_value_unset(&value); + } + + g_free(old_property); + } + + /* Now bind to the new value */ panel->color1_btn_id = xfconf_g_property_bind_gdkcolor(channel, buf, G_OBJECT(panel->color1_btn), "color"); } g_free(buf); + /* color 2 button */ buf = xfdesktop_settings_generate_per_workspace_binding_string(panel, "color2"); if(remove_binding) { xfconf_g_property_unbind(panel->color2_btn_id); } else { + /* If the 2nd color doesn't exist, try to load the old one */ + if(!xfconf_channel_has_property(channel, buf)) { + GValue value = { 0, }; + old_property = xfdesktop_settings_generate_old_binding_string(panel, "color1"); + + xfconf_channel_get_property(channel, old_property, &value); + + if(G_VALUE_HOLDS_BOXED(&value)) { + gtk_color_button_set_color(GTK_COLOR_BUTTON(panel->color1_btn), + g_value_get_boxed(&value)); + g_value_unset(&value); + } + + g_free(old_property); + } + + /* Now bind to the new value */ panel->color2_btn_id = xfconf_g_property_bind_gdkcolor(channel, buf, G_OBJECT(panel->color2_btn), "color"); } g_free(buf); - /* Cycle timer options */ + /* enable cycle timer check box */ buf = xfdesktop_settings_generate_per_workspace_binding_string(panel, "backdrop-cycle-enable"); if(remove_binding) { xfconf_g_property_unbind_by_property(channel, buf, @@ -1117,6 +1231,7 @@ xfdesktop_settings_background_tab_change_bindings(AppearancePanel *panel, } g_free(buf); + /* cycle timer spin box */ buf = xfdesktop_settings_generate_per_workspace_binding_string(panel, "backdrop-cycle-timer"); if(remove_binding) { xfconf_g_property_unbind_by_property(channel, buf, @@ -1129,6 +1244,7 @@ xfdesktop_settings_background_tab_change_bindings(AppearancePanel *panel, } g_free(buf); + /* cycle random order check box */ buf = xfdesktop_settings_generate_per_workspace_binding_string(panel, "backdrop-cycle-random-order"); if(remove_binding) { xfconf_g_property_unbind_by_property(channel, buf, @@ -1159,6 +1275,11 @@ cb_update_background_tab(WnckWindow *wnck_window, WnckWorkspace *wnck_workspace = NULL; GdkScreen *screen; + /* If we haven't found our window return now and wait for that */ + if(panel->wnck_window == NULL) + return; + + /* Get all the new settings for comparison */ screen = gtk_widget_get_screen(panel->image_iconview); wnck_workspace = wnck_window_get_workspace(wnck_window); @@ -1168,18 +1289,31 @@ cb_update_background_tab(WnckWindow *wnck_window, 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_name != NULL && - g_strcmp0(panel->monitor_name, monitor_name) == 0) { - return; + /* Most of the time we won't change monitor, screen, or workspace so try + * to bail out now if we can */ + /* Check to see if we haven't changed workspace or screen */ + if(panel->workspace == workspace_num && panel->screen == screen_num) + { + /* do we support monitor names? */ + if(panel->monitor_name != NULL || monitor_name != NULL) { + /* Check if we haven't changed monitors (by name) */ + if(g_strcmp0(panel->monitor_name, monitor_name) == 0) { + g_free(monitor_name); + return; + } + } else { + /* Check if we haven't changed monitors (by number) */ + if(panel->monitor == monitor_num) { + return; + } + } } TRACE("screen, monitor, or workspace changed"); - /* remove the old bindings */ - if(panel->monitor != -1 && panel->workspace != -1) { + /* remove the old bindings if there are any */ + if(panel->color1_btn_id || panel->color2_btn_id) { + DBG("removing old bindings"); xfdesktop_settings_background_tab_change_bindings(panel, TRUE); } @@ -1218,10 +1352,83 @@ cb_workspace_changed(WnckScreen *screen, gpointer user_data) { AppearancePanel *panel = user_data; + WnckWorkspace *active_workspace; + gint new_num = -1; + + g_return_if_fail(WNCK_IS_SCREEN(screen)); + + /* Update the current workspace number */ + active_workspace = wnck_screen_get_active_workspace(screen); + if(WNCK_IS_WORKSPACE(active_workspace)) + new_num = wnck_workspace_get_number(active_workspace); + + /* This will sometimes fail to update */ + if(new_num != -1) + panel->active_workspace = new_num; + + DBG("active_workspace now %d", panel->active_workspace); + + /* Call cb_update_background_tab in case this is a pinned window */ + if(panel->wnck_window != NULL) + cb_update_background_tab(panel->wnck_window, panel); +} + +static void +cb_workspace_count_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); + if(panel->wnck_window != NULL) + cb_update_background_tab(panel->wnck_window, user_data); +} + +static void +cb_window_opened(WnckScreen *screen, + WnckWindow *window, + gpointer user_data) +{ + AppearancePanel *panel = user_data; + GtkWidget *toplevel; + WnckWorkspace *workspace; + + /* If we already found our window, exit */ + if(panel->wnck_window != NULL) + return; + + toplevel = gtk_widget_get_toplevel(panel->image_iconview); + + /* If they don't match then it's not our window, exit */ + if(wnck_window_get_xid(window) != GDK_WINDOW_XID(gtk_widget_get_window(toplevel))) + return; + + DBG("Found our window"); + panel->wnck_window = window; + + /* 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); + + workspace = wnck_window_get_workspace(window); + + /* Update the active workspace number */ + cb_workspace_changed(screen, workspace, panel); + + /* Update the background settings */ + cb_update_background_tab(window, panel); + + /* If it's a pinned window get the active workspace */ + if(workspace == NULL) + workspace = wnck_screen_get_workspace(screen, panel->active_workspace); + + /* Update the frame name */ + xfdesktop_settings_update_iconview_frame_name(panel, workspace); } static void @@ -1292,8 +1499,7 @@ xfdesktop_settings_setup_image_iconview(AppearancePanel *panel) static void xfdesktop_settings_dialog_setup_tabs(GtkBuilder *main_gxml, XfconfChannel *channel, - GdkScreen *screen, - gulong window_xid) + GdkScreen *screen) { GtkWidget *appearance_container, *chk_custom_font_size, *spin_font_size, *w, *box, *spin_icon_size, @@ -1357,34 +1563,24 @@ xfdesktop_settings_dialog_setup_tabs(GtkBuilder *main_gxml, panel->channel = channel; panel->screen = gdk_screen_get_number(screen); - /* We have to force wnck to initialize */ wnck_screen = wnck_screen_get(panel->screen); - wnck_screen_force_update(wnck_screen); - panel->wnck_window = wnck_window_get(window_xid); - - if(panel->wnck_window == NULL) - panel->wnck_window = wnck_screen_get_active_window(wnck_screen); - /* 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); + /* watch for workspace changes */ g_signal_connect(wnck_screen, "workspace-created", - G_CALLBACK(cb_workspace_changed), panel); + G_CALLBACK(cb_workspace_count_changed), panel); g_signal_connect(wnck_screen, "workspace-destroyed", - G_CALLBACK(cb_workspace_changed), panel); + G_CALLBACK(cb_workspace_count_changed), panel); g_signal_connect(wnck_screen, "active-workspace-changed", - G_CALLBACK(cb_workspace_changed), panel); + G_CALLBACK(cb_workspace_changed), panel); + + /* watch for window-opened so we can find our window and track it's changes */ + g_signal_connect(wnck_screen, "window-opened", + G_CALLBACK(cb_window_opened), panel); + + /* watch for monitor changes */ 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; - panel->workspace = -1; - panel->monitor_name = NULL; - appearance_gxml = gtk_builder_new(); if(!gtk_builder_add_from_string(appearance_gxml, xfdesktop_settings_appearance_frame_ui, @@ -1445,8 +1641,8 @@ xfdesktop_settings_dialog_setup_tabs(GtkBuilder *main_gxml, 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); + gtk_combo_box_set_active(GTK_COMBO_BOX(panel->image_style_combo), XFCE_BACKDROP_IMAGE_STRETCHED); + gtk_combo_box_set_active(GTK_COMBO_BOX(panel->color_style_combo), XFCE_BACKDROP_COLOR_SOLID); /* Use these settings for all workspaces checkbox */ panel->chk_apply_to_all = GTK_WIDGET(gtk_builder_get_object(appearance_gxml, @@ -1567,6 +1763,7 @@ main(int argc, char **argv) { XfconfChannel *channel; GtkBuilder *gxml; + GdkScreen *screen; GError *error = NULL; #ifdef G_ENABLE_DEBUG @@ -1580,7 +1777,6 @@ main(int argc, char **argv) #if !GLIB_CHECK_VERSION(2, 32, 0) g_thread_init(NULL); #endif - gdk_threads_init(); if(!gtk_init_with_args(&argc, &argv, "", option_entries, PACKAGE, &error)) { if(G_LIKELY(error)) { @@ -1634,14 +1830,12 @@ main(int argc, char **argv) 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), - GDK_WINDOW_XID(gtk_widget_get_window(dialog))); + + screen = gtk_widget_get_screen(dialog); /* To prevent the settings dialog to be saved in the session */ gdk_x11_set_sm_client_id("FAKE ID"); - gtk_main(); } else { GtkWidget *plug, *plug_child; @@ -1655,13 +1849,14 @@ main(int argc, char **argv) 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(); + screen = gtk_widget_get_screen(plug); } + xfdesktop_settings_dialog_setup_tabs(gxml, channel, screen); + + gtk_main(); + g_object_unref(G_OBJECT(gxml)); g_object_unref(G_OBJECT(channel)); diff --git a/settings/xfce-backdrop-settings.desktop.in b/settings/xfce-backdrop-settings.desktop.in index ce87ed2e..e20ac187 100644 --- a/settings/xfce-backdrop-settings.desktop.in +++ b/settings/xfce-backdrop-settings.desktop.in @@ -9,6 +9,6 @@ Type=Application Categories=XFCE;GTK;Settings;DesktopSettings;X-XFCE-SettingsDialog;X-XFCE-PersonalSettings; OnlyShowIn=XFCE; StartupNotify=true -X-XfcePluggable=true +X-XfcePluggable=false X-XfceHelpComponent=xfdesktop X-XfceHelpPage=preferences diff --git a/src/xfce-backdrop.c b/src/xfce-backdrop.c index c4827a92..ff0d7844 100644 --- a/src/xfce-backdrop.c +++ b/src/xfce-backdrop.c @@ -267,12 +267,14 @@ xfce_backdrop_class_init(XfceBackdropClass *klass) | G_PARAM_STATIC_NICK \ | G_PARAM_STATIC_BLURB) + /* Defaults to an invalid color style so that + * xfce_workspace_migrate_backdrop_color_style can handle it properly */ g_object_class_install_property(gobject_class, PROP_COLOR_STYLE, g_param_spec_enum("color-style", "color style", "color style", XFCE_TYPE_BACKDROP_COLOR_STYLE, - XFCE_BACKDROP_COLOR_SOLID, + XFCE_BACKDROP_COLOR_INVALID, XFDESKTOP_PARAM_FLAGS)); g_object_class_install_property(gobject_class, PROP_COLOR1, @@ -289,19 +291,23 @@ xfce_backdrop_class_init(XfceBackdropClass *klass) GDK_TYPE_COLOR, XFDESKTOP_PARAM_FLAGS)); + /* Defaults to an invalid image style so that + * xfce_workspace_migrate_backdrop_image_style can handle it properly */ g_object_class_install_property(gobject_class, PROP_IMAGE_STYLE, g_param_spec_enum("image-style", "image style", "image style", XFCE_TYPE_BACKDROP_IMAGE_STYLE, - XFCE_BACKDROP_IMAGE_SCALED, + XFCE_BACKDROP_IMAGE_INVALID, XFDESKTOP_PARAM_FLAGS)); + /* The DEFAULT_BACKDROP is provided in the function + * xfce_workspace_migrate_backdrop_image instead of here */ g_object_class_install_property(gobject_class, PROP_IMAGE_FILENAME, g_param_spec_string("image-filename", "image filename", "image filename", - DEFAULT_BACKDROP, + NULL, XFDESKTOP_PARAM_FLAGS)); g_object_class_install_property(gobject_class, PROP_BACKDROP_CYCLE_ENABLE, @@ -553,8 +559,8 @@ xfce_backdrop_set_color_style(XfceBackdrop *backdrop, XfceBackdropColorStyle style) { g_return_if_fail(XFCE_IS_BACKDROP(backdrop)); - g_return_if_fail((int)style >= 0 && style <= XFCE_BACKDROP_COLOR_TRANSPARENT); - + g_return_if_fail((int)style >= -1 && style <= XFCE_BACKDROP_COLOR_TRANSPARENT); + if(style != backdrop->priv->color_style) { xfce_backdrop_clear_cached_image(backdrop); backdrop->priv->color_style = style; @@ -651,8 +657,7 @@ xfce_backdrop_get_second_color(XfceBackdrop *backdrop, * @backdrop: An #XfceBackdrop. * @style: An XfceBackdropImageStyle. * - * Sets the image style to be used for the #XfceBackdrop. "AUTO" attempts to - * pick the best of "TILED" or "STRETCHED" based on the image size. + * Sets the image style to be used for the #XfceBackdrop. * "STRETCHED" will stretch the image to the full width and height of the * #XfceBackdrop, while "SCALED" will resize the image to fit the desktop * while maintaining the image's aspect ratio. @@ -692,7 +697,7 @@ xfce_backdrop_set_image_filename(XfceBackdrop *backdrop, const gchar *filename) { g_return_if_fail(XFCE_IS_BACKDROP(backdrop)); - TRACE("entering"); + TRACE("entering, filename %s", filename); g_free(backdrop->priv->image_path); @@ -769,6 +774,14 @@ xfce_backdrop_get_cycle_timer(XfceBackdrop *backdrop) return backdrop->priv->cycle_timer; } +/** + * xfce_backdrop_set_cycle_backdrop: + * @backdrop: An #XfceBackdrop. + * @cycle_backdrop: True to cycle backdrops every cycle_timer minutes + * + * Setting cycle_backdrop to TRUE will begin cycling this backdrop based on + * the cycle_timer value set in xfce_backdrop_set_cycle_timer. + **/ void xfce_backdrop_set_cycle_backdrop(XfceBackdrop *backdrop, gboolean cycle_backdrop) @@ -793,6 +806,16 @@ xfce_backdrop_get_cycle_backdrop(XfceBackdrop *backdrop) return backdrop->priv->cycle_backdrop; } +/** + * xfce_backdrop_set_random_order: + * @backdrop: An #XfceBackdrop. + * @random_order: When TRUE and the backdrops are set to cycle, a random image + * image will be choosen when it cycles. + * + * When cycling backdrops, they will either be show sequentially (and this value + * will be FALSE) or they will be selected at random. The images are choosen from + * the same folder the current backdrop image file is in. + **/ void xfce_backdrop_set_random_order(XfceBackdrop *backdrop, gboolean random_order) @@ -821,6 +844,12 @@ xfce_backdrop_generate_canvas(XfceBackdrop *backdrop) w = backdrop->priv->width; h = backdrop->priv->height; + /* In case we somehow end up here, give a warning and apply a temp fix */ + if(backdrop->priv->color_style == XFCE_BACKDROP_COLOR_INVALID) { + g_warning("xfce_backdrop_generate_canvas: Invalid color style"); + backdrop->priv->color_style = XFCE_BACKDROP_COLOR_SOLID; + } + if(backdrop->priv->color_style == XFCE_BACKDROP_COLOR_SOLID) final_image = create_solid(&backdrop->priv->color1, w, h, FALSE, 0xff); else if(backdrop->priv->color_style == XFCE_BACKDROP_COLOR_TRANSPARENT) { @@ -862,9 +891,14 @@ xfce_backdrop_image_data_release(XfceBackdropImageData *image_data) } -/* Returns the composited backdrop image if one has been generated. If it +/** + * xfce_backdrop_get_pixbuf: + * @backdrop: An #XfceBackdrop. + * + * Returns the composited backdrop image if one has been generated. If it * returns NULL, call xfce_backdrop_generate_async to create the pixbuf. - * Free with g_object_unref() when you are finished. */ + * Free with g_object_unref() when you are finished. + **/ GdkPixbuf * xfce_backdrop_get_pixbuf(XfceBackdrop *backdrop) { @@ -876,13 +910,19 @@ xfce_backdrop_get_pixbuf(XfceBackdrop *backdrop) return NULL; } -/* Generates the final composited, resized image from the #XfceBackdrop. - * Emits the "ready" signal when the image has been created */ +/** + * xfce_backdrop_generate_async: + * @backdrop: An #XfceBackdrop. + * + * Generates the final composited, resized image from the #XfceBackdrop. + * Emits the "ready" signal when the image has been created. + **/ void xfce_backdrop_generate_async(XfceBackdrop *backdrop) { GFile *file; XfceBackdropImageData *image_data = NULL; + const gchar *image_path; TRACE("entering"); @@ -897,16 +937,22 @@ xfce_backdrop_generate_async(XfceBackdrop *backdrop) } /* If we aren't going to display an image then just create the canvas */ - if(backdrop->priv->image_style == XFCE_BACKDROP_IMAGE_NONE - || !backdrop->priv->image_path) { + if(backdrop->priv->image_style == XFCE_BACKDROP_IMAGE_NONE) { backdrop->priv->pix = xfce_backdrop_generate_canvas(backdrop); g_signal_emit(G_OBJECT(backdrop), backdrop_signals[BACKDROP_READY], 0); return; } - file = g_file_new_for_path(backdrop->priv->image_path); - image_data = g_new0(XfceBackdropImageData, 1); + /* If we're trying to display an image, attempt to use the one the user + * set. If there's none set at all, fall back to our default */ + if(backdrop->priv->image_path != NULL) + image_path = backdrop->priv->image_path; + else + image_path = DEFAULT_BACKDROP; + + file = g_file_new_for_path(image_path); + image_data = g_new0(XfceBackdropImageData, 1); backdrop->priv->image_data = image_data; image_data->backdrop = backdrop; @@ -937,6 +983,11 @@ xfce_backdrop_loader_size_prepared_cb(GdkPixbufLoader *loader, TRACE("entering"); + if(backdrop->priv->image_style == XFCE_BACKDROP_IMAGE_INVALID) { + g_warning("Invalid image style, setting to XFCE_BACKDROP_IMAGE_STRETCHED"); + backdrop->priv->image_style = XFCE_BACKDROP_IMAGE_STRETCHED; + } + switch(backdrop->priv->image_style) { case XFCE_BACKDROP_IMAGE_CENTERED: case XFCE_BACKDROP_IMAGE_TILED: diff --git a/src/xfce-backdrop.h b/src/xfce-backdrop.h index 1aba049d..8a46927e 100644 --- a/src/xfce-backdrop.h +++ b/src/xfce-backdrop.h @@ -40,6 +40,7 @@ typedef struct _XfceBackdropPriv XfceBackdropPriv; typedef enum { + XFCE_BACKDROP_IMAGE_INVALID = -1, XFCE_BACKDROP_IMAGE_NONE = 0, XFCE_BACKDROP_IMAGE_CENTERED, XFCE_BACKDROP_IMAGE_TILED, @@ -51,6 +52,7 @@ typedef enum typedef enum { + XFCE_BACKDROP_COLOR_INVALID = -1, XFCE_BACKDROP_COLOR_SOLID = 0, XFCE_BACKDROP_COLOR_HORIZ_GRADIENT, XFCE_BACKDROP_COLOR_VERT_GRADIENT, diff --git a/src/xfce-desktop.c b/src/xfce-desktop.c index aeebd574..4bd7040b 100644 --- a/src/xfce-desktop.c +++ b/src/xfce-desktop.c @@ -326,8 +326,12 @@ create_bg_pixmap(GdkScreen *gscreen, gpointer user_data) g_return_val_if_fail(XFCE_IS_DESKTOP(desktop), NULL); - if(desktop->priv->workspaces == NULL) + /* If the workspaces haven't been created yet there's no need to do the + * background pixmap */ + if(desktop->priv->workspaces == NULL) { + DBG("exiting, desktop->priv->workspaces == NULL"); return NULL; + } w = gdk_screen_get_width(gscreen); h = gdk_screen_get_height(gscreen); @@ -603,7 +607,7 @@ workspace_changed_cb(WnckScreen *wnck_screen, 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)) { + if(!xfce_backdrop_compare_backdrops(current_backdrop, new_backdrop) || !desktop->priv->bg_pixmap) { /* only update monitors that require it */ backdrop_changed_cb(new_backdrop, user_data); } @@ -1007,17 +1011,15 @@ xfce_desktop_realize(GtkWidget *widget) wnck_screen = wnck_screen_get(gdk_screen_get_number(desktop->priv->gscreen)); desktop->priv->wnck_screen = wnck_screen; + /* Watch for single workspace setting changes */ 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"); - /* Start with an invalid workspace so it updates */ - desktop->priv->current_workspace = -1; - + /* watch for workspace changes */ g_signal_connect(desktop->priv->wnck_screen, "active-workspace-changed", G_CALLBACK(workspace_changed_cb), desktop); g_signal_connect(desktop->priv->wnck_screen, "workspace-created", @@ -1025,8 +1027,7 @@ xfce_desktop_realize(GtkWidget *widget) g_signal_connect(desktop->priv->wnck_screen, "workspace-destroyed", G_CALLBACK(workspace_destroyed_cb), desktop); - xfce_desktop_monitors_changed(desktop->priv->gscreen, desktop); - + /* watch for screen changes */ g_signal_connect(G_OBJECT(desktop->priv->gscreen), "size-changed", G_CALLBACK(screen_size_changed_cb), desktop); g_signal_connect(G_OBJECT(desktop->priv->gscreen), "composited-changed", @@ -1495,8 +1496,10 @@ xfce_desktop_set_single_workspace_mode(XfceDesktop *desktop, 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); + /* If the desktop has been realized then fake a screen size change to + * update the backdrop. There's no reason to if there's no desktop yet */ + if(gtk_widget_get_realized(GTK_WIDGET(desktop))) + screen_size_changed_cb(desktop->priv->gscreen, desktop); } static void diff --git a/src/xfce-workspace.c b/src/xfce-workspace.c index 70796d8d..936b9602 100644 --- a/src/xfce-workspace.c +++ b/src/xfce-workspace.c @@ -314,6 +314,149 @@ xfce_workspace_get_property(GObject *object, } } +/* Attempts to get the backdrop colors from the xfdesktop pre-4.11 format */ +static void +xfce_workspace_migrate_backdrop_color_style(XfceWorkspace *workspace, + XfceBackdrop *backdrop, + guint monitor) +{ + XfconfChannel *channel = workspace->priv->channel; + char buf[1024]; + gint pp_len; + GValue value = { 0, }; + + TRACE("entering"); + + /* Use the old property format */ + g_snprintf(buf, sizeof(buf), "%smonitor%d/", + workspace->priv->property_prefix, monitor); + pp_len = strlen(buf); + + /* Color style */ + buf[pp_len] = 0; + g_strlcat(buf, "color-style", sizeof(buf)); + xfconf_channel_get_property(channel, buf, &value); + + if(G_VALUE_HOLDS_INT(&value)) { + xfce_backdrop_set_color_style(backdrop, g_value_get_int(&value)); + g_value_unset(&value); + } + + /* first color */ + buf[pp_len] = 0; + g_strlcat(buf, "color1", sizeof(buf)); + xfconf_channel_get_property(channel, buf, &value); + + if(G_VALUE_HOLDS_BOXED(&value)) { + xfce_backdrop_set_first_color(backdrop, g_value_get_boxed(&value)); + g_value_unset(&value); + } + + /* second color */ + buf[pp_len] = 0; + g_strlcat(buf, "color2", sizeof(buf)); + xfconf_channel_get_property(channel, buf, &value); + + if(G_VALUE_HOLDS_BOXED(&value)) { + xfce_backdrop_set_second_color(backdrop, g_value_get_boxed(&value)); + g_value_unset(&value); + } + + /* Fallback to solid if nothing was set anywhere */ + if(xfce_backdrop_get_color_style(backdrop) == XFCE_BACKDROP_COLOR_INVALID) + xfce_backdrop_set_color_style(backdrop, XFCE_BACKDROP_COLOR_SOLID); +} + +/* Attempts to get the backdrop image from the xfdesktop pre-4.11 format */ +static void +xfce_workspace_migrate_backdrop_image(XfceWorkspace *workspace, + XfceBackdrop *backdrop, + guint monitor) +{ + XfconfChannel *channel = workspace->priv->channel; + char buf[1024]; + gint pp_len; + GValue value = { 0, }; + const gchar *filename; + + TRACE("entering"); + + /* Use the old property format */ + g_snprintf(buf, sizeof(buf), "%smonitor%d/", + workspace->priv->property_prefix, monitor); + pp_len = strlen(buf); + + /* Try the old backdrop */ + buf[pp_len] = 0; + g_strlcat(buf, "image-path", sizeof(buf)); + xfconf_channel_get_property(channel, buf, &value); + + /* Either there was a backdrop to migrate from or we use the backdrop + * we provide as a default */ + if(G_VALUE_HOLDS_STRING(&value)) + filename = g_value_get_string(&value); + else + filename = DEFAULT_BACKDROP; + + xfce_backdrop_set_image_filename(backdrop, filename); + + if(G_VALUE_HOLDS_STRING(&value)) + g_value_unset(&value); +} + +/* Attempts to get the image style from the xfdesktop pre-4.11 format */ +static void +xfce_workspace_migrate_backdrop_image_style(XfceWorkspace *workspace, + XfceBackdrop *backdrop, + guint monitor) +{ + XfconfChannel *channel = workspace->priv->channel; + char buf[1024]; + gint pp_len; + GValue value = { 0, }; + + TRACE("entering"); + + /* Use the old property format */ + g_snprintf(buf, sizeof(buf), "%smonitor%d/", + workspace->priv->property_prefix, monitor); + pp_len = strlen(buf); + + /* show image */ + buf[pp_len] = 0; + g_strlcat(buf, "image-show", sizeof(buf)); + xfconf_channel_get_property(channel, buf, &value); + + if(G_VALUE_HOLDS_BOOLEAN(&value)) { + gboolean show_image = g_value_get_boolean(&value); + + /* if we aren't showing the image, set the style and exit the function + * so we don't set the style to something else */ + if(!show_image) { + xfce_backdrop_set_image_style(backdrop, XFCE_BACKDROP_IMAGE_NONE); + g_value_unset(&value); + return; + } + + g_value_unset(&value); + } + + /* image style */ + buf[pp_len] = 0; + g_strlcat(buf, "image-style", sizeof(buf)); + xfconf_channel_get_property(channel, buf, &value); + + if(G_VALUE_HOLDS_INT(&value)) { + XfceBackdropImageStyle style; + style = xfce_translate_image_styles(g_value_get_int(&value)); + xfce_backdrop_set_image_style(backdrop, style); + g_value_unset(&value); + } else { + /* If no value was ever set default to stretched */ + xfce_backdrop_set_image_style(backdrop, XFCE_BACKDROP_IMAGE_STRETCHED); + } +} + static void xfce_workspace_connect_backdrop_settings(XfceWorkspace *workspace, XfceBackdrop *backdrop, @@ -378,6 +521,18 @@ xfce_workspace_connect_backdrop_settings(XfceWorkspace *workspace, xfconf_g_property_bind(channel, buf, G_TYPE_STRING, G_OBJECT(backdrop), "image-filename"); + /* If we didn't get a filename try to load one from a previous version */ + if(xfce_backdrop_get_image_filename(backdrop) == NULL) + xfce_workspace_migrate_backdrop_image(workspace, backdrop, monitor); + + /* If we didn't get a proper color style, attempt to get the old one */ + if(xfce_backdrop_get_color_style(backdrop) == XFCE_BACKDROP_COLOR_INVALID) + xfce_workspace_migrate_backdrop_color_style(workspace, backdrop, monitor); + + /* Same for image style, this also deals with 'Auto' */ + if(xfce_backdrop_get_image_style(backdrop) == XFCE_BACKDROP_IMAGE_INVALID) + xfce_workspace_migrate_backdrop_image_style(workspace, backdrop, monitor); + g_free(monitor_name); } |