[Xfce4-commits] <thunar:nick/desktop> Bladiebla.
Nick Schermer
noreply at xfce.org
Sat Feb 2 12:38:04 CET 2013
Updating branch refs/heads/nick/desktop
to eaad5bc29bbe5e6ad965a728c2887ad75275ced8 (commit)
from dae9c330340b7fecf0986734956b794251128831 (commit)
commit eaad5bc29bbe5e6ad965a728c2887ad75275ced8
Author: Nick Schermer <nick at xfce.org>
Date: Wed Jan 16 23:07:55 2013 +0100
Bladiebla.
configure.ac.in | 2 +-
thunar/Makefile.am | 11 +-
thunar/main.c | 12 +
thunar/thunar-abstract-icon-view.c | 2 +-
thunar/thunar-desktop-background-icon-view.c | 170 ++++++
thunar/thunar-desktop-background-icon-view.h | 40 ++
thunar/thunar-desktop-background.c | 844 ++++++++++++++++++++++++++
thunar/thunar-desktop-background.h | 42 ++
thunar/thunar-desktop-preferences-dialog.c | 413 +++++++++++++
thunar/thunar-desktop-preferences-dialog.h | 42 ++
thunar/thunar-desktop-window.c | 260 ++++++++
thunar/thunar-desktop-window.h | 44 ++
thunar/thunar-enum-types.c | 121 +++--
thunar/thunar-enum-types.h | 39 ++
thunar/thunar-gtk-extensions.c | 5 +-
thunar/thunar-list-model.c | 29 +-
thunar/thunar-list-model.h | 8 +
thunar/thunar-standard-view.c | 19 +-
18 files changed, 2058 insertions(+), 45 deletions(-)
diff --git a/configure.ac.in b/configure.ac.in
index 93629a9..dc23fda 100644
--- a/configure.ac.in
+++ b/configure.ac.in
@@ -116,7 +116,7 @@ dnl **********************************
AC_CHECK_HEADERS([ctype.h errno.h fcntl.h grp.h limits.h locale.h memory.h \
paths.h pwd.h sched.h signal.h stdarg.h stdlib.h string.h \
sys/mman.h sys/param.h sys/stat.h sys/time.h sys/types.h \
- sys/uio.h sys/wait.h time.h])
+ sys/uio.h sys/wait.h time.h math.h])
dnl ************************************
dnl *** Check for standard functions ***
diff --git a/thunar/Makefile.am b/thunar/Makefile.am
index 04846de..0a8c1b0 100644
--- a/thunar/Makefile.am
+++ b/thunar/Makefile.am
@@ -59,6 +59,14 @@ thunar_SOURCES = \
thunar-create-dialog.h \
thunar-deep-count-job.h \
thunar-deep-count-job.c \
+ thunar-desktop-background.c \
+ thunar-desktop-background.h \
+ thunar-desktop-background-icon-view.c \
+ thunar-desktop-background-icon-view.h \
+ thunar-desktop-preferences-dialog.c \
+ thunar-desktop-preferences-dialog.h \
+ thunar-desktop-window.c \
+ thunar-desktop-window.h \
thunar-details-view-ui.h \
thunar-details-view.c \
thunar-details-view.h \
@@ -243,7 +251,8 @@ thunar_LDADD = \
$(LIBSM_LIBS) \
$(LIBSTARTUP_NOTIFICATION_LIBS) \
$(LIBXFCE4UI_LIBS) \
- $(XFCONF_LIBS)
+ $(XFCONF_LIBS) \
+ -lm
thunar_DEPENDENCIES = \
$(top_builddir)/thunarx/libthunarx-$(THUNARX_VERSION_API).la
diff --git a/thunar/main.c b/thunar/main.c
index 4c31953..f9c393e 100644
--- a/thunar/main.c
+++ b/thunar/main.c
@@ -44,11 +44,13 @@
#include <thunar/thunar-session-client.h>
#include <thunar/thunar-stock.h>
#include <thunar/thunar-preferences.h>
+#include <thunar/thunar-desktop-window.h>
/* --- globals --- */
static gboolean opt_bulk_rename = FALSE;
+static gboolean opt_desktop = FALSE;
static gboolean opt_daemon = FALSE;
static gchar *opt_sm_client_id = NULL;
static gboolean opt_quit = FALSE;
@@ -60,6 +62,7 @@ static gboolean opt_version = FALSE;
static GOptionEntry option_entries[] =
{
{ "bulk-rename", 'B', 0, G_OPTION_ARG_NONE, &opt_bulk_rename, N_ ("Open the bulk rename dialog"), NULL, },
+ { "desktop", 0, 0, G_OPTION_ARG_NONE, &opt_desktop, N_ ("Let Thunar manage the desktop"), NULL, },
#ifdef HAVE_DBUS
{ "daemon", 0, 0, G_OPTION_ARG_NONE, &opt_daemon, N_ ("Run in daemon mode"), NULL, },
#else
@@ -120,6 +123,7 @@ main (int argc, char **argv)
gchar *working_directory;
gchar **filenames = NULL;
const gchar *startup_id;
+ GtkWidget *window;
/* setup translation domain */
xfce_textdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR, "UTF-8");
@@ -208,6 +212,14 @@ main (int argc, char **argv)
}
#endif
+ if (G_UNLIKELY (opt_desktop))
+ {
+ window = thunar_desktop_window_new ();
+ gtk_widget_show (window);
+ gtk_main ();
+ return 0;
+ }
+
/* determine the current working directory */
working_directory = g_get_current_dir ();
diff --git a/thunar/thunar-abstract-icon-view.c b/thunar/thunar-abstract-icon-view.c
index c79b747..c9a4d7d 100644
--- a/thunar/thunar-abstract-icon-view.c
+++ b/thunar/thunar-abstract-icon-view.c
@@ -98,7 +98,7 @@ static void thunar_abstract_icon_view_zoom_level_changed (ThunarAbstr
struct _ThunarAbstractIconViewPrivate
{
/* the UI manager merge id for the abstract icon view */
- gint ui_merge_id;
+ guint ui_merge_id;
/* mouse gesture support */
gint gesture_start_x;
diff --git a/thunar/thunar-desktop-background-icon-view.c b/thunar/thunar-desktop-background-icon-view.c
new file mode 100644
index 0000000..32ad82b
--- /dev/null
+++ b/thunar/thunar-desktop-background-icon-view.c
@@ -0,0 +1,170 @@
+/*-
+ * Copyright (c) 2013 Nick Schermer <nick at xfce.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <thunar/thunar-desktop-background-icon-view.h>
+#include <thunar/thunar-private.h>
+
+
+
+static void thunar_desktop_background_icon_view_finalize (GObject *object);
+static AtkObject *thunar_desktop_background_icon_view_get_accessible (GtkWidget *widget);
+static gboolean thunar_desktop_background_icon_view_visible_func (ThunarFile *file,
+ gpointer data);
+
+
+
+struct _ThunarDesktopBackgroundIconViewClass
+{
+ ThunarAbstractIconViewClass __parent__;
+};
+
+struct _ThunarDesktopBackgroundIconView
+{
+ ThunarAbstractIconView __parent__;
+
+ GHashTable *mime_types;
+};
+
+
+
+G_DEFINE_TYPE (ThunarDesktopBackgroundIconView, thunar_desktop_background_icon_view, THUNAR_TYPE_ABSTRACT_ICON_VIEW)
+
+
+
+static void
+thunar_desktop_background_icon_view_class_init (ThunarDesktopBackgroundIconViewClass *klass)
+{
+ ThunarStandardViewClass *thunarstandard_view_class;
+ GtkWidgetClass *gtkwidget_class;
+ GObjectClass *gobject_class;
+
+ gobject_class = G_OBJECT_CLASS (klass);
+ gobject_class->finalize = thunar_desktop_background_icon_view_finalize;
+
+ gtkwidget_class = GTK_WIDGET_CLASS (klass);
+ gtkwidget_class->get_accessible = thunar_desktop_background_icon_view_get_accessible;
+
+ thunarstandard_view_class = THUNAR_STANDARD_VIEW_CLASS (klass);
+ thunarstandard_view_class->zoom_level_property_name = NULL;
+}
+
+
+
+static void
+thunar_desktop_background_icon_view_init (ThunarDesktopBackgroundIconView *icon_view)
+{
+ ThunarListModel *model;
+ GSList *formats;
+ GSList *lp;
+ gchar **mime_types;
+ guint n;
+ GtkWidget *exo_view;
+
+ /* only a single selection is possible */
+ exo_view = gtk_bin_get_child (GTK_BIN (icon_view));
+ exo_icon_view_set_selection_mode (EXO_ICON_VIEW (exo_view), GTK_SELECTION_BROWSE);
+ exo_icon_view_set_enable_search (EXO_ICON_VIEW (exo_view), TRUE);
+
+ /* setup the icon renderer */
+ g_object_set (G_OBJECT (THUNAR_STANDARD_VIEW (icon_view)->icon_renderer),
+ "size", THUNAR_ICON_SIZE_LARGEST,
+ NULL);
+
+ /* setup the name renderer */
+ g_object_set (G_OBJECT (THUNAR_STANDARD_VIEW (icon_view)->name_renderer),
+ "visible", FALSE, NULL);
+
+ /* collect gdk supported types */
+ icon_view->mime_types = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+
+ /* get a list of all formats supported by GdkPixbuf */
+ formats = gdk_pixbuf_get_formats ();
+ for (lp = formats; lp != NULL; lp = lp->next)
+ {
+ /* ignore the disabled ones */
+ if (!gdk_pixbuf_format_is_disabled (lp->data))
+ {
+ /* get a list of MIME types supported by this format */
+ mime_types = gdk_pixbuf_format_get_mime_types (lp->data);
+ if (G_UNLIKELY (mime_types == NULL))
+ continue;
+
+ /* put them all in the unqiue MIME type hash table */
+ for (n = 0; mime_types[n] != NULL; ++n)
+ g_hash_table_replace (icon_view->mime_types, g_strdup (mime_types[n]), NULL);
+
+ /* free the string array */
+ g_strfreev (mime_types);
+ }
+ }
+ g_slist_free (formats);
+
+ /* only show gdkpixbuf supported files */
+ model = THUNAR_STANDARD_VIEW (icon_view)->model;
+ thunar_list_model_set_visible_func (model, thunar_desktop_background_icon_view_visible_func, icon_view);
+}
+
+
+
+static void
+thunar_desktop_background_icon_view_finalize (GObject *object)
+{
+ ThunarDesktopBackgroundIconView *icon_view = THUNAR_DESKTOP_BACKGROUND_ICON_VIEW (object);
+
+ g_hash_table_destroy (icon_view->mime_types);
+
+ (*G_OBJECT_CLASS (thunar_desktop_background_icon_view_parent_class)->finalize) (object);
+}
+
+
+
+static AtkObject*
+thunar_desktop_background_icon_view_get_accessible (GtkWidget *widget)
+{
+ AtkObject *object;
+
+ /* query the atk object for the icon view class */
+ object = (*GTK_WIDGET_CLASS (thunar_desktop_background_icon_view_parent_class)->get_accessible) (widget);
+
+ /* set custom Atk properties for the icon view */
+ if (G_LIKELY (object != NULL))
+ {
+ atk_object_set_description (object, _("Icon based directory listing"));
+ atk_object_set_name (object, _("Icon view"));
+ atk_object_set_role (object, ATK_ROLE_DIRECTORY_PANE);
+ }
+
+ return object;
+}
+
+
+
+static gboolean
+thunar_desktop_background_icon_view_visible_func (ThunarFile *file,
+ gpointer data)
+{
+ ThunarDesktopBackgroundIconView *icon_view = THUNAR_DESKTOP_BACKGROUND_ICON_VIEW (data);
+
+ return g_hash_table_lookup_extended (icon_view->mime_types,
+ thunar_file_get_content_type (file),
+ NULL, NULL);
+}
diff --git a/thunar/thunar-desktop-background-icon-view.h b/thunar/thunar-desktop-background-icon-view.h
new file mode 100644
index 0000000..9015827
--- /dev/null
+++ b/thunar/thunar-desktop-background-icon-view.h
@@ -0,0 +1,40 @@
+/*-
+ * Copyright (c) 2013 Nick Schermer <nick at xfce.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __THUNAR_DESKTOP_BACKGROUND_ICON_VIEW_H__
+#define __THUNAR_DESKTOP_BACKGROUND_ICON_VIEW_H__
+
+#include <thunar/thunar-abstract-icon-view.h>
+
+G_BEGIN_DECLS
+
+typedef struct _ThunarDesktopBackgroundIconViewClass ThunarDesktopBackgroundIconViewClass;
+typedef struct _ThunarDesktopBackgroundIconView ThunarDesktopBackgroundIconView;
+
+#define THUNAR_TYPE_DESKTOP_BACKGROUND_ICON_VIEW (thunar_desktop_background_icon_view_get_type ())
+#define THUNAR_DESKTOP_BACKGROUND_ICON_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_TYPE_DESKTOP_BACKGROUND_ICON_VIEW, ThunarDesktopBackgroundIconView))
+#define THUNAR_DESKTOP_BACKGROUND_ICON_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), THUNAR_TYPE_DESKTOP_BACKGROUND_ICON_VIEW, ThunarDesktopBackgroundIconViewClass))
+#define THUNAR_IS_DESKTOP_BACKGROUND_ICON_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THUNAR_TYPE_DESKTOP_BACKGROUND_ICON_VIEW))
+#define THUNAR_IS_DESKTOP_BACKGROUND_ICON_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), THUNAR_TYPE_DESKTOP_BACKGROUND_ICON_VIEW))
+#define THUNAR_DESKTOP_BACKGROUND_ICON_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_TYPE_DESKTOP_BACKGROUND_ICON_VIEW, ThunarDesktopBackgroundIconViewClass))
+
+GType thunar_desktop_background_icon_view_get_type (void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* !__THUNAR_DESKTOP_BACKGROUND_ICON_VIEW_H__ */
diff --git a/thunar/thunar-desktop-background.c b/thunar/thunar-desktop-background.c
new file mode 100644
index 0000000..3f562d4
--- /dev/null
+++ b/thunar/thunar-desktop-background.c
@@ -0,0 +1,844 @@
+/*-
+ * Copyright (c) 2012 Nick Schermer <nick at xfce.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_MATH_H
+#include <math.h>
+#endif
+
+#include <exo/exo.h>
+#include <xfconf/xfconf.h>
+
+#ifdef GDK_WINDOWING_X11
+#include <gdk/gdkx.h>
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#endif
+
+#include <thunar/thunar-private.h>
+#include <thunar/thunar-desktop-background.h>
+#include <thunar/thunar-enum-types.h>
+#include <thunar/thunar-gdk-extensions.h>
+
+#define FADE_ANIMATION_USEC ((gdouble) G_USEC_PER_SEC / 2.0) /* 0.5 second */
+#define FADE_ANIMATION_FPS (1000 / 60)
+
+
+
+enum
+{
+ PROP_0,
+ PROP_SOURCE_WINDOW,
+};
+
+
+
+static void thunar_desktop_background_constructed (GObject *object);
+static void thunar_desktop_background_finalize (GObject *object);
+static void thunar_desktop_background_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+static void thunar_desktop_background_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void thunar_desktop_background_expose (ThunarDesktopBackground *background,
+ gboolean pseudo_transparency);
+static void thunar_desktop_background_paint (ThunarDesktopBackground *background,
+ gboolean fade_animation);
+static void thunar_desktop_background_settings_changed (XfconfChannel *channel,
+ const gchar *property,
+ const GValue *value,
+ ThunarDesktopBackground *background);
+static guint thunar_desktop_background_settings_enum (XfconfChannel *channel,
+ GType enum_type,
+ const gchar *prop);
+static void thunar_desktop_background_settings_color (XfconfChannel *channel,
+ const gchar *prop,
+ GdkColor *color_return);
+
+
+
+struct _ThunarDesktopBackgroundClass
+{
+ GObjectClass __parent__;
+};
+
+struct _ThunarDesktopBackground
+{
+ GObject __parent__;
+
+ XfconfChannel *settings;
+
+ GdkWindow *source_window;
+ GdkPixmap *pixmap;
+
+ guint fade_timeout_id;
+};
+
+typedef struct
+{
+ ThunarDesktopBackground *background;
+ cairo_surface_t *start_surface;
+ cairo_surface_t *end_surface;
+ gint64 start_time;
+}
+BackgroundFade;
+
+
+
+G_DEFINE_TYPE (ThunarDesktopBackground, thunar_desktop_background, G_TYPE_OBJECT)
+
+
+
+static void
+thunar_desktop_background_class_init (ThunarDesktopBackgroundClass *klass)
+{
+ GObjectClass *gobject_class;
+
+ gobject_class = G_OBJECT_CLASS (klass);
+ gobject_class->constructed = thunar_desktop_background_constructed;
+ gobject_class->finalize = thunar_desktop_background_finalize;
+ gobject_class->get_property = thunar_desktop_background_get_property;
+ gobject_class->set_property = thunar_desktop_background_set_property;
+
+ g_object_class_install_property (gobject_class,
+ PROP_SOURCE_WINDOW,
+ g_param_spec_object ("source-window", NULL, NULL,
+ GDK_TYPE_WINDOW,
+ EXO_PARAM_READWRITE
+ | G_PARAM_CONSTRUCT_ONLY));
+}
+
+
+
+static void
+thunar_desktop_background_init (ThunarDesktopBackground *background)
+{
+ background->settings = xfconf_channel_get ("thunar-desktop");
+ g_signal_connect (G_OBJECT (background->settings), "property-changed",
+ G_CALLBACK (thunar_desktop_background_settings_changed), background);
+}
+
+
+
+static void
+thunar_desktop_background_constructed (GObject *object)
+{
+ ThunarDesktopBackground *background = THUNAR_DESKTOP_BACKGROUND (object);
+ GdkScreen *screen;
+
+ _thunar_return_if_fail (GDK_IS_DRAWABLE (background->source_window));
+
+ /* create pixmap we can draw on */
+ screen = gdk_window_get_screen (background->source_window);
+ background->pixmap = gdk_pixmap_new (GDK_DRAWABLE (background->source_window),
+ gdk_screen_get_width (screen),
+ gdk_screen_get_height (screen),
+ -1);
+
+ /* render images and colors */
+ thunar_desktop_background_paint (background, FALSE);
+
+ /* set our background */
+ gdk_window_set_back_pixmap (background->source_window, background->pixmap, FALSE);
+
+ /* expose views */
+ thunar_desktop_background_expose (background, TRUE);
+}
+
+
+
+static void
+thunar_desktop_background_finalize (GObject *object)
+{
+ ThunarDesktopBackground *background = THUNAR_DESKTOP_BACKGROUND (object);
+ GdkWindow *root_window;
+
+ /* unset the backgrounds */
+ gdk_window_set_back_pixmap (background->source_window, NULL, FALSE);
+ root_window = gdk_screen_get_root_window (gdk_window_get_screen (background->source_window));
+ gdk_window_set_back_pixmap (root_window, NULL, FALSE);
+
+#ifdef GDK_WINDOWING_X11
+ /* unset speudo-transparency */
+ gdk_error_trap_push ();
+ gdk_property_delete (root_window, gdk_atom_intern_static_string ("_XROOTPMAP_ID"));
+ gdk_property_delete (root_window, gdk_atom_intern_static_string ("ESETROOT_PMAP_ID"));
+ gdk_error_trap_pop ();
+#endif
+
+ if (background->fade_timeout_id != 0)
+ g_source_remove (background->fade_timeout_id);
+
+ if (background->source_window != NULL)
+ g_object_unref (G_OBJECT (background->source_window));
+ if (background->pixmap != NULL)
+ g_object_unref (G_OBJECT (background->pixmap));
+
+ g_signal_handlers_disconnect_by_func (G_OBJECT (background->settings),
+ G_CALLBACK (thunar_desktop_background_settings_changed), background);
+
+ (*G_OBJECT_CLASS (thunar_desktop_background_parent_class)->finalize) (object);
+}
+
+
+
+static void
+thunar_desktop_background_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ //ThunarDesktopBackground *background = THUNAR_DESKTOP_BACKGROUND (object);
+
+ switch (prop_id)
+ {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+
+
+static void
+thunar_desktop_background_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ ThunarDesktopBackground *background = THUNAR_DESKTOP_BACKGROUND (object);
+
+ switch (prop_id)
+ {
+ case PROP_SOURCE_WINDOW:
+ _thunar_return_if_fail (background->source_window == NULL);
+ background->source_window = g_value_dup_object (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+
+
+static void
+thunar_desktop_background_paint_image (cairo_t *cr,
+ const GdkRectangle *area,
+ GdkInterpType interp,
+ ThunarBackgroundStyle style,
+ const GdkPixbuf *src_pixbuf)
+{
+ gint src_w, src_h;
+ GdkPixbuf *dst_pixbuf = NULL;
+ gint dx, dy;
+ gint dst_w, dst_h;
+ gdouble wratio, hratio;
+ gboolean scale_dst = FALSE;
+ cairo_pattern_t *pattern;
+
+ _thunar_return_if_fail (GDK_IS_PIXBUF (src_pixbuf));
+
+ src_w = gdk_pixbuf_get_width (src_pixbuf);
+ src_h = gdk_pixbuf_get_height (src_pixbuf);
+
+ dx = area->x;
+ dy = area->y;
+
+ dst_w = area->width;
+ dst_h = area->height;
+
+ switch (style)
+ {
+ case THUNAR_BACKGROUND_STYLE_NONE:
+ return;
+
+ case THUNAR_BACKGROUND_STYLE_TILED:
+ break;
+
+ case THUNAR_BACKGROUND_STYLE_CENTERED:
+ dx += (area->width - src_w) / 2;
+ dy += (area->height - src_h) / 2;
+ break;
+
+ case THUNAR_BACKGROUND_STYLE_STRETCHED:
+ if (src_w != dst_w || src_h != dst_h)
+ {
+ /* scale to fill screen */
+ scale_dst = TRUE;
+ }
+ break;
+
+ case THUNAR_BACKGROUND_STYLE_SCALED:
+ if (src_w != dst_w || src_h != dst_h)
+ {
+ /* calculate the new dimensions */
+ wratio = (gdouble) src_w / (gdouble) dst_w;
+ hratio = (gdouble) src_h / (gdouble) dst_h;
+
+ if (hratio > wratio)
+ dst_w = rint (src_w / hratio);
+ else
+ dst_h = rint (src_h / wratio);
+
+ /* scale to monitor, no corp */
+ scale_dst = TRUE;
+ }
+ break;
+
+ case THUNAR_BACKGROUND_STYLE_SPANNED:
+ case THUNAR_BACKGROUND_STYLE_ZOOMED:
+ if (src_w != dst_w || src_h != dst_h)
+ {
+ /* calculate the new dimensions */
+ wratio = (gdouble) src_w / (gdouble) dst_w;
+ hratio = (gdouble) src_h / (gdouble) dst_h;
+
+ if (hratio < wratio)
+ dst_w = rint (src_w / hratio);
+ else
+ dst_h = rint (src_h / wratio);
+
+ /* scale to monitor, no corp */
+ scale_dst = TRUE;
+ }
+ break;
+ }
+
+ if (scale_dst)
+ {
+ /* scale source */
+ dst_pixbuf = gdk_pixbuf_scale_simple (src_pixbuf, MAX (1, dst_w), MAX (1, dst_h), interp);
+
+ /* center on monitor */
+ dx += (area->width - dst_w) / 2;
+ dy += (area->height - dst_h) / 2;
+ }
+ else
+ {
+ /* no scaling was required, ref source */
+ dst_pixbuf = g_object_ref (G_OBJECT (src_pixbuf));
+ }
+
+ /* clip area */
+ cairo_save (cr);
+ gdk_cairo_rectangle (cr, area);
+ cairo_clip (cr);
+
+ /* paint the image */
+ thunar_gdk_cairo_set_source_pixbuf (cr, dst_pixbuf, dx, dy);
+
+ if (style == THUNAR_BACKGROUND_STYLE_TILED)
+ {
+ pattern = cairo_get_source (cr);
+ cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
+ }
+
+ cairo_paint (cr);
+ cairo_restore (cr);
+
+ g_object_unref (G_OBJECT (dst_pixbuf));
+}
+
+
+
+static void
+thunar_desktop_background_paint_color_fill (cairo_t *cr,
+ const GdkRectangle *area,
+ ThunarBackgroundColorStyle style,
+ GdkColor *color_start,
+ GdkColor *color_end)
+{
+ cairo_pattern_t *pattern;
+ gint x1, y1;
+ gint radius;
+
+ switch (style)
+ {
+ case THUNAR_BACKGROUND_COLOR_STYLE_SOLID:
+ gdk_cairo_set_source_color (cr, color_start);
+ cairo_rectangle (cr, area->x, area->y, area->width, area->height);
+ cairo_fill (cr);
+ break;
+
+ case THUNAR_BACKGROUND_COLOR_STYLE_HORIZONTAL:
+ x1 = area->x + area->width;
+ y1 = area->y;
+ goto paint_linear;
+
+ case THUNAR_BACKGROUND_COLOR_STYLE_VERTICAL:
+ x1 = area->x;
+ y1 = area->y + area->height;
+
+ paint_linear:
+
+ pattern = cairo_pattern_create_linear (area->x, area->y, x1, y1);
+
+ paint_gradient:
+
+ if (cairo_pattern_status (pattern) == CAIRO_STATUS_SUCCESS)
+ {
+ /* set start and stop color */
+ cairo_pattern_add_color_stop_rgb (pattern, 0,
+ color_start->red / 65535.0,
+ color_start->green / 65535.0,
+ color_start->blue / 65535.0);
+ cairo_pattern_add_color_stop_rgb (pattern, 1,
+ color_end->red / 65535.0,
+ color_end->green / 65535.0,
+ color_end->blue / 65535.0);
+
+ /* draw rectangle with gradient fill */
+ cairo_save (cr);
+ cairo_rectangle (cr, area->x, area->y, area->width, area->height);
+ cairo_set_source (cr, pattern);
+ cairo_fill (cr);
+ cairo_restore (cr);
+ }
+ cairo_pattern_destroy (pattern);
+ break;
+
+ case THUNAR_BACKGROUND_COLOR_STYLE_RADIAL:
+ x1 = area->x + area->width / 2;
+ y1 = area->y + area->height / 2;
+ radius = MAX (area->width, area->height) / 2;
+
+ pattern = cairo_pattern_create_radial (x1, y1, radius, x1, y1, 0);
+ goto paint_gradient;
+ break;
+ }
+}
+
+
+
+static cairo_surface_t *
+thunar_desktop_background_get_surface (ThunarDesktopBackground *background,
+ cairo_t *cr_source)
+{
+ cairo_surface_t *copy;
+ cairo_surface_t *target;
+ gint w, h;
+ cairo_t *cr;
+
+ target = cairo_get_target (cr_source);
+ gdk_drawable_get_size (GDK_DRAWABLE (background->pixmap), &w, &h);
+ copy = cairo_surface_create_similar (target, cairo_surface_get_content (target), w, h);
+
+ cr = cairo_create (copy);
+ cairo_set_source_surface (cr, target, 0.0, 0.0);
+ cairo_paint (cr);
+
+ if (cairo_status (cr) != CAIRO_STATUS_SUCCESS)
+ {
+ cairo_surface_destroy (copy);
+ copy = NULL;
+ }
+
+ cairo_destroy (cr);
+
+ return copy;
+}
+
+
+
+static void
+thunar_desktop_background_expose (ThunarDesktopBackground *background,
+ gboolean pseudo_transparency)
+{
+ GdkWindow *root_window;
+ GdkScreen *screen;
+#ifdef GDK_WINDOWING_X11
+ Window pixmap_xid;
+ GdkAtom atom_pixmap;
+#endif
+
+ /* invalidate area of our window */
+ gdk_window_clear (background->source_window);
+
+ /* leave if we're not updating the fake transparency */
+ if (!pseudo_transparency)
+ return;
+
+ gdk_error_trap_push ();
+
+ /* root window background */
+ screen = gdk_window_get_screen (background->source_window);
+ root_window = gdk_screen_get_root_window (screen);
+ gdk_window_set_back_pixmap (root_window, background->pixmap, FALSE);
+ gdk_window_clear (root_window);
+
+#ifdef GDK_WINDOWING_X11
+ /* pseudo atoms for aterm / xterm etc */
+ atom_pixmap = gdk_atom_intern_static_string ("PIXMAP");
+ pixmap_xid = gdk_x11_drawable_get_xid (GDK_DRAWABLE (background->pixmap));
+
+ gdk_property_change (root_window,
+ gdk_atom_intern_static_string ("ESETROOT_PMAP_ID"),
+ atom_pixmap, 32,
+ GDK_PROP_MODE_REPLACE, (guchar *) &pixmap_xid, 1);
+
+ gdk_property_change (root_window,
+ gdk_atom_intern_static_string ("_XROOTPMAP_ID"),
+ atom_pixmap, 32,
+ GDK_PROP_MODE_REPLACE, (guchar *) &pixmap_xid, 1);
+#endif
+
+ gdk_error_trap_pop ();
+}
+
+
+
+static gboolean
+thunar_desktop_background_fade_running (gpointer data)
+{
+ BackgroundFade *fade = data;
+ gdouble opacity;
+ cairo_t *cr;
+
+ _thunar_return_val_if_fail (THUNAR_IS_DESKTOP_BACKGROUND (fade->background), FALSE);
+ _thunar_return_val_if_fail (GDK_IS_DRAWABLE (fade->background->pixmap), FALSE);
+ _thunar_return_val_if_fail (GDK_IS_WINDOW (fade->background->source_window), FALSE);
+
+ /* get fade opacity based on system time */
+ if (fade->start_time > 0)
+ opacity = (g_get_real_time () - fade->start_time) / FADE_ANIMATION_USEC;
+ else
+ opacity = 0;
+
+ /* prepare cairo context */
+ cr = gdk_cairo_create (GDK_DRAWABLE (fade->background->pixmap));
+ g_assert (cairo_status (cr) == CAIRO_STATUS_SUCCESS);
+
+ cairo_set_source_surface (cr, fade->start_surface, 0.0, 0.0);
+ cairo_paint (cr);
+
+ if (G_LIKELY (opacity > 0))
+ {
+ cairo_set_source_surface (cr, fade->end_surface, 0.0, 0.0);
+ cairo_paint_with_alpha (cr, CLAMP (opacity, 0.0, 1.0));
+ }
+
+ cairo_destroy (cr);
+
+ /* expose */
+ thunar_desktop_background_expose (fade->background, opacity >= 1.0);
+
+ return opacity < 1.0;
+}
+
+
+
+static void
+thunar_desktop_background_fade_completed (gpointer data)
+{
+ BackgroundFade *fade = data;
+
+ _thunar_return_if_fail (THUNAR_IS_DESKTOP_BACKGROUND (fade->background));
+ _thunar_return_if_fail (GDK_IS_DRAWABLE (fade->background->pixmap));
+ _thunar_return_if_fail (GDK_IS_WINDOW (fade->background->source_window));
+
+ fade->background->fade_timeout_id = 0;
+
+ /* cleanup */
+ cairo_surface_destroy (fade->start_surface);
+ cairo_surface_destroy (fade->end_surface);
+ g_slice_free (BackgroundFade, fade);
+}
+
+
+
+static void
+thunar_desktop_background_paint (ThunarDesktopBackground *background,
+ gboolean fade_animation)
+{
+ cairo_t *cr;
+ GdkScreen *screen;
+ gint n, n_monitors;
+ GdkRectangle area;
+ GdkInterpType interp;
+ GdkPixbuf *pixbuf;
+ cairo_surface_t *start_surface;
+ cairo_surface_t *end_surface;
+ BackgroundFade *fade;
+ ThunarBackgroundStyle bg_style;
+ ThunarBackgroundColorStyle color_style;
+ GError *error = NULL;
+ gchar *monitor_name;
+ gint screen_num;
+ gchar prop[128];
+ GdkColor color_start;
+ GdkColor color_end;
+ gchar *filename;
+ gchar *uri;
+
+ _thunar_return_if_fail (THUNAR_IS_DESKTOP_BACKGROUND (background));
+ _thunar_return_if_fail (GDK_IS_DRAWABLE (background->pixmap));
+
+ /* stop pending animation */
+ if (background->fade_timeout_id != 0)
+ g_source_remove (background->fade_timeout_id);
+
+ /* prepare cairo context */
+ cr = gdk_cairo_create (GDK_DRAWABLE (background->pixmap));
+ g_assert (cairo_status (cr) == CAIRO_STATUS_SUCCESS);
+
+ /* cache the old surface for the fade animation */
+ if (fade_animation
+ && xfconf_channel_get_bool (background->settings, "/background/fade-animation", TRUE))
+ start_surface = thunar_desktop_background_get_surface (background, cr);
+ else
+ start_surface = NULL;
+
+ /* screen info */
+ screen = gdk_window_get_screen (background->source_window);
+ screen_num = gdk_screen_get_number (screen);
+ n_monitors = gdk_screen_get_n_monitors (screen);
+
+ /* if the screen has a bit depth of less than 24bpp, using bilinear
+ * filtering looks crappy (mainly with gradients). */
+ if (gdk_drawable_get_depth (GDK_DRAWABLE (background->source_window)) < 24)
+ interp = GDK_INTERP_HYPER;
+ else
+ interp = GDK_INTERP_BILINEAR;
+
+ /* draw each monitor */
+ for (n = 0; n < n_monitors; n++)
+ {
+ /* get the monitor name */
+ monitor_name = gdk_screen_get_monitor_plug_name (screen, n);
+ if (G_UNLIKELY (monitor_name == NULL))
+ monitor_name = g_strdup_printf ("monitor-%d", n);
+
+ /* get background style */
+ g_snprintf (prop, sizeof (prop), "/background/screen-%d/%s/style", screen_num, monitor_name);
+ bg_style = thunar_desktop_background_settings_enum (background->settings,
+ THUNAR_TYPE_BACKGROUND_STYLE,
+ prop);
+
+ /* spanning works only on settings of the 1st monitor */
+ if (bg_style == THUNAR_BACKGROUND_STYLE_SPANNED)
+ {
+ area.x = area.y = 0;
+ area.width = gdk_screen_get_width (screen);
+ area.height = gdk_screen_get_height (screen);
+ }
+ else
+ {
+ /* get area of the monitor */
+ gdk_screen_get_monitor_geometry (screen, n, &area);
+ }
+
+ pixbuf = NULL;
+
+ if (bg_style != THUNAR_BACKGROUND_STYLE_NONE)
+ {
+ /* get file name */
+ g_snprintf (prop, sizeof (prop), "/background/screen-%d/%s/uri", screen_num, monitor_name);
+ uri = xfconf_channel_get_string (background->settings, prop, NULL);
+
+ /* only support local files */
+ if (G_LIKELY (uri != NULL
+ && g_str_has_prefix (uri, "file:///")))
+ {
+ filename = g_filename_from_uri (uri, NULL, NULL);
+ if (G_LIKELY (filename != NULL))
+ {
+ /* load the image into the memory (exo uses mmap) */
+ pixbuf = exo_gdk_pixbuf_new_from_file_at_max_size (filename, G_MAXINT, G_MAXINT, TRUE, &error);
+ if (G_UNLIKELY (pixbuf == NULL))
+ {
+ g_warning ("Unable to load image \"%s\": %s",
+ filename, error != NULL ? error->message : "No error");
+ g_error_free (error);
+ }
+ g_free (filename);
+ }
+ }
+ g_free (uri);
+ }
+
+ /* check if we should draw a background color (if we are not sure the background
+ * image is not going to overlap the color anyway) */
+ if (pixbuf == NULL
+ || gdk_pixbuf_get_has_alpha (pixbuf)
+ || bg_style == THUNAR_BACKGROUND_STYLE_NONE
+ || bg_style == THUNAR_BACKGROUND_STYLE_TILED
+ || bg_style == THUNAR_BACKGROUND_STYLE_CENTERED
+ || bg_style == THUNAR_BACKGROUND_STYLE_SCALED)
+ {
+ /* get background style */
+ g_snprintf (prop, sizeof (prop), "/background/screen-%d/%s/color-style", screen_num, monitor_name);
+ color_style = thunar_desktop_background_settings_enum (background->settings,
+ THUNAR_TYPE_BACKGROUND_COLOR_STYLE,
+ prop);
+
+ /* load the colors */
+ g_snprintf (prop, sizeof (prop), "/background/screen-%d/%s/color-start", screen_num, monitor_name);
+ thunar_desktop_background_settings_color (background->settings, prop, &color_start);
+ g_snprintf (prop, sizeof (prop), "/background/screen-%d/%s/color-end", screen_num, monitor_name);
+ thunar_desktop_background_settings_color (background->settings, prop, &color_end);
+
+ /* paint */
+ thunar_desktop_background_paint_color_fill (cr, &area, color_style, &color_start, &color_end);
+ }
+
+ if (G_LIKELY (pixbuf != NULL))
+ {
+ /* paint the image */
+ thunar_desktop_background_paint_image (cr, &area, interp, bg_style, pixbuf);
+ g_object_unref (G_OBJECT (pixbuf));
+ }
+
+ g_free (monitor_name);
+
+ /* only need to draw once for spanning */
+ if (bg_style == THUNAR_BACKGROUND_STYLE_SPANNED)
+ break;
+ }
+
+ /* if a fade animation was requested, start the timeout */
+ if (start_surface != NULL)
+ {
+ end_surface = thunar_desktop_background_get_surface (background, cr);
+ if (G_LIKELY (end_surface != NULL))
+ {
+ fade = g_slice_new0 (BackgroundFade);
+ fade->background = background;
+ fade->start_surface = start_surface;
+ fade->end_surface = end_surface;
+
+ /* "restore" the old background (start_time == 0) */
+ thunar_desktop_background_fade_running (fade);
+
+ /* start animation */
+ fade->start_time = g_get_real_time ();
+ background->fade_timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT_IDLE, FADE_ANIMATION_FPS,
+ thunar_desktop_background_fade_running, fade,
+ thunar_desktop_background_fade_completed);
+ }
+ else
+ {
+ /* cairo error, clear the start surface */
+ cairo_surface_destroy (start_surface);
+ thunar_desktop_background_expose (background, TRUE);
+ }
+ }
+ else if (fade_animation)
+ {
+ /* animations are disabled, clear the window now */
+ thunar_desktop_background_expose (background, TRUE);
+ }
+
+ cairo_destroy (cr);
+}
+
+
+
+static void
+thunar_desktop_background_settings_changed (XfconfChannel *channel,
+ const gchar *property,
+ const GValue *value,
+ ThunarDesktopBackground *background)
+{
+ _thunar_return_if_fail (THUNAR_IS_DESKTOP_BACKGROUND (background));
+ _thunar_return_if_fail (XFCONF_IS_CHANNEL (channel));
+ _thunar_return_if_fail (background->source_window == NULL
+ || GDK_IS_DRAWABLE (background->source_window));
+
+ /* only respond to background changes */
+ if (g_str_has_prefix (property, "/background/screen-"))
+ thunar_desktop_background_paint (background, TRUE);
+}
+
+
+
+static guint
+thunar_desktop_background_settings_enum (XfconfChannel *channel,
+ GType enum_type,
+ const gchar *prop)
+{
+ gchar *str;
+ GEnumClass *klass;
+ guint value = 0;
+ guint n;
+
+ _thunar_return_val_if_fail (XFCONF_IS_CHANNEL (channel), 0);
+
+ /* get string name from settings */
+ str = xfconf_channel_get_string (channel, prop, NULL);
+ if (str == NULL)
+ return value;
+
+ /* determine the enum value matching the src... */
+ klass = g_type_class_ref (enum_type);
+ _thunar_assert (G_IS_ENUM_CLASS (klass));
+ for (n = 0; n < klass->n_values; ++n)
+ {
+ if (exo_str_is_equal (klass->values[n].value_name, str))
+ {
+ value = klass->values[n].value;
+ break;
+ }
+ }
+ g_type_class_unref (klass);
+ g_free (str);
+
+ return value;
+}
+
+
+
+static void
+thunar_desktop_background_settings_color (XfconfChannel *channel,
+ const gchar *prop,
+ GdkColor *color_return)
+{
+ gchar *str;
+
+ _thunar_return_if_fail (XFCONF_IS_CHANNEL (channel));
+
+ /* get string name from settings */
+ str = xfconf_channel_get_string (channel, prop, "#000000");
+ if (!gdk_color_parse (str, color_return))
+ {
+ g_warning ("Failed to parse color %s from %s", str, prop);
+
+ /* return black */
+ color_return->red = 0;
+ color_return->green = 0;
+ color_return->blue = 0;
+ }
+ g_free (str);
+}
+
+
+
+ThunarDesktopBackground *
+thunar_desktop_background_new (GdkWindow *source_window)
+{
+ _thunar_return_val_if_fail (GDK_IS_WINDOW (source_window), NULL);
+ return g_object_new (THUNAR_TYPE_DESKTOP_BACKGROUND,
+ "source-window", source_window, NULL);
+}
diff --git a/thunar/thunar-desktop-background.h b/thunar/thunar-desktop-background.h
new file mode 100644
index 0000000..ddd65d8
--- /dev/null
+++ b/thunar/thunar-desktop-background.h
@@ -0,0 +1,42 @@
+/*-
+ * Copyright (c) 2012 Nick Schermer <nick at xfce.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __THUNAR_DESKTOP_BACKGROUND_H__
+#define __THUNAR_DESKTOP_BACKGROUND_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+typedef struct _ThunarDesktopBackgroundClass ThunarDesktopBackgroundClass;
+typedef struct _ThunarDesktopBackground ThunarDesktopBackground;
+
+#define THUNAR_TYPE_DESKTOP_BACKGROUND (thunar_desktop_background_get_type ())
+#define THUNAR_DESKTOP_BACKGROUND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_TYPE_DESKTOP_BACKGROUND, ThunarDesktopBackground))
+#define THUNAR_DESKTOP_BACKGROUND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), THUNAR_TYPE_DESKTOP_BACKGROUND, ThunarDesktopBackgroundClass))
+#define THUNAR_IS_DESKTOP_BACKGROUND(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THUNAR_TYPE_DESKTOP_BACKGROUND))
+#define THUNAR_IS_DESKTOP_BACKGROUND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), THUNAR_TYPE_DESKTOP_BACKGROUND))
+#define THUNAR_DESKTOP_BACKGROUND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_TYPE_DESKTOP_BACKGROUND, ThunarDesktopBackgroundClass))
+
+GType thunar_desktop_background_get_type (void) G_GNUC_CONST;
+
+ThunarDesktopBackground *thunar_desktop_background_new (GdkWindow *source_window);
+
+G_END_DECLS
+
+#endif /* !__THUNAR_DESKTOP_BACKGROUND_H__ */
diff --git a/thunar/thunar-desktop-preferences-dialog.c b/thunar/thunar-desktop-preferences-dialog.c
new file mode 100644
index 0000000..1b28a6b
--- /dev/null
+++ b/thunar/thunar-desktop-preferences-dialog.c
@@ -0,0 +1,413 @@
+/*-
+ * Copyright (c) 2013 Nick Schermer <nick at xfce.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <libxfce4ui/libxfce4ui.h>
+#include <xfconf/xfconf.h>
+
+#include <thunar/thunar-desktop-preferences-dialog.h>
+#include <thunar/thunar-enum-types.h>
+#include <thunar/thunar-desktop-background-icon-view.h>
+#include <thunar/thunar-private.h>
+
+
+
+static void thunar_desktop_preferences_dialog_finalize (GObject *object);
+static void thunar_desktop_preferences_dialog_realize (GtkWidget *widget);
+static void thunar_desktop_preferences_dialog_screen_changed (GtkWidget *widget,
+ GdkScreen *old_screen);
+static void thunar_desktop_preferences_dialog_response (GtkDialog *dialog,
+ gint response);
+static void thunar_desktop_preferences_dialog_background_changed (ThunarDesktopPreferencesDialog *dialog);
+static void thunar_desktop_preferences_dialog_background_prop (ThunarDesktopPreferencesDialog *dialog);
+static void thunar_desktop_preferences_dialog_update (ThunarDesktopPreferencesDialog *dialog);
+static void thunar_desktop_preferences_dialog_folder_changed (ThunarDesktopPreferencesDialog *dialog);
+
+
+struct _ThunarDesktopPreferencesDialogClass
+{
+ XfceTitledDialogClass __parent__;
+};
+
+struct _ThunarDesktopPreferencesDialog
+{
+ XfceTitledDialog __parent__;
+
+ XfconfChannel *settings;
+
+ gchar *background_prop;
+
+ GtkWidget *view;
+ GtkWidget *folder_chooser;
+};
+
+
+
+G_DEFINE_TYPE (ThunarDesktopPreferencesDialog, thunar_desktop_preferences_dialog, XFCE_TYPE_TITLED_DIALOG)
+
+
+
+static void
+thunar_desktop_preferences_dialog_class_init (ThunarDesktopPreferencesDialogClass *klass)
+{
+ GtkDialogClass *gtkdialog_class;
+ GObjectClass *gobject_class;
+ GtkWidgetClass *gtkwidget_class;
+
+ gobject_class = G_OBJECT_CLASS (klass);
+ gobject_class->finalize = thunar_desktop_preferences_dialog_finalize;
+
+ gtkwidget_class = GTK_WIDGET_CLASS (klass);
+ gtkwidget_class->realize = thunar_desktop_preferences_dialog_realize;
+ gtkwidget_class->screen_changed = thunar_desktop_preferences_dialog_screen_changed;
+
+ gtkdialog_class = GTK_DIALOG_CLASS (klass);
+ gtkdialog_class->response = thunar_desktop_preferences_dialog_response;
+}
+
+
+
+static void
+thunar_desktop_preferences_dialog_init (ThunarDesktopPreferencesDialog *dialog)
+{
+ GtkWidget *notebook;
+ GtkWidget *label;
+ GtkWidget *vbox;
+ GtkWidget *hbox;
+ GtkWidget *combo;
+ GtkWidget *button;
+ GtkWidget *button2;
+ GEnumClass *klass;
+ guint n;
+ GtkSizeGroup *size_group;
+
+ dialog->settings = xfconf_channel_get ("thunar-desktop");
+
+ /* configure the dialog properties */
+ gtk_window_set_icon_name (GTK_WINDOW (dialog), "preferences-desktop-wallpaper");
+ gtk_window_set_title (GTK_WINDOW (dialog), _("Desktop Preferences"));
+ gtk_window_set_default_size (GTK_WINDOW (dialog), 900, 700);
+
+ /* add "Help" and "Close" buttons */
+ gtk_dialog_add_buttons (GTK_DIALOG (dialog),
+ GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
+ GTK_STOCK_HELP, GTK_RESPONSE_HELP,
+ NULL);
+
+ notebook = gtk_notebook_new ();
+ gtk_container_set_border_width (GTK_CONTAINER (notebook), 6);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), notebook, TRUE, TRUE, 0);
+ gtk_widget_show (notebook);
+
+ /*
+ Display
+ */
+ label = gtk_label_new (_("Background"));
+ vbox = g_object_new (GTK_TYPE_VBOX, "border-width", 12, "spacing", 6, NULL);
+ gtk_notebook_append_page (GTK_NOTEBOOK (notebook), vbox, label);
+ gtk_widget_show (label);
+ gtk_widget_show (vbox);
+
+ dialog->view = g_object_new (THUNAR_TYPE_DESKTOP_BACKGROUND_ICON_VIEW, NULL);
+ g_signal_connect_swapped (G_OBJECT (dialog->view), "notify::selected-files",
+ G_CALLBACK (thunar_desktop_preferences_dialog_background_changed), dialog);
+ gtk_box_pack_start (GTK_BOX (vbox), dialog->view, TRUE, TRUE, 0);
+ gtk_widget_show (dialog->view);
+
+ size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
+
+ hbox = gtk_hbox_new (FALSE, 12);
+ gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
+ gtk_widget_show (hbox);
+
+ label = gtk_label_new_with_mnemonic ("_Folder:");
+ gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
+ gtk_size_group_add_widget (size_group, label);
+ gtk_widget_show (label);
+
+ dialog->folder_chooser = gtk_file_chooser_button_new (_("Choose a background images folder"), GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
+ gtk_box_pack_start (GTK_BOX (hbox), dialog->folder_chooser, FALSE, TRUE, 0);
+ gtk_label_set_mnemonic_widget (GTK_LABEL (label), dialog->folder_chooser);
+ gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (dialog->folder_chooser), TRUE);
+ g_signal_connect_swapped (G_OBJECT (dialog->folder_chooser), "current-folder-changed",
+ G_CALLBACK (thunar_desktop_preferences_dialog_folder_changed), dialog);
+ gtk_widget_show (dialog->folder_chooser);
+
+ /* spacer */
+ label = g_object_new (GTK_TYPE_LABEL, NULL);
+ gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0);
+ gtk_widget_show (label);
+
+ label = gtk_label_new_with_mnemonic ("_Style:");
+ gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
+ gtk_widget_show (label);
+
+ combo = gtk_combo_box_text_new ();
+ gtk_box_pack_start (GTK_BOX (hbox), combo, FALSE, TRUE, 0);
+ gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo);
+ gtk_widget_show (combo);
+
+ klass = g_type_class_ref (THUNAR_TYPE_BACKGROUND_STYLE);
+ for (n = 0; n < klass->n_values; ++n)
+ gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), _(klass->values[n].value_nick));
+ g_type_class_unref (klass);
+
+ hbox = gtk_hbox_new (FALSE, 12);
+ gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
+ gtk_widget_show (hbox);
+
+ label = gtk_label_new_with_mnemonic ("C_olors:");
+ gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
+ gtk_size_group_add_widget (size_group, label);
+ gtk_widget_show (label);
+
+ g_object_unref (size_group);
+
+ combo = gtk_combo_box_text_new ();
+ gtk_box_pack_start (GTK_BOX (hbox), combo, FALSE, TRUE, 0);
+ gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo);
+ gtk_widget_show (combo);
+
+ klass = g_type_class_ref (THUNAR_TYPE_BACKGROUND_COLOR_STYLE);
+ for (n = 0; n < klass->n_values; ++n)
+ gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), _(klass->values[n].value_nick));
+ g_type_class_unref (klass);
+
+ button = gtk_color_button_new ();
+ gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
+ gtk_widget_show (button);
+
+ button = gtk_color_button_new ();
+ gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
+ g_object_bind_property (combo, "active", button, "sensitive", G_BINDING_SYNC_CREATE);
+ gtk_widget_show (button);
+
+ hbox = gtk_hbox_new (FALSE, 12);
+ gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
+ gtk_widget_show (hbox);
+
+ button = gtk_check_button_new_with_mnemonic (_("Ch_ange picture"));
+ gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
+ gtk_widget_show (button);
+
+ combo = gtk_combo_box_text_new ();
+ g_object_bind_property (button, "active", combo, "sensitive", G_BINDING_SYNC_CREATE);
+ gtk_box_pack_start (GTK_BOX (hbox), combo, FALSE, TRUE, 0);
+ gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), _("During login"));
+ gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), _("Every 10 seconds"));
+ gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), _("Every minute"));
+ gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), _("Every 5 minutes"));
+ gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), _("Every 15 minutes"));
+ gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), _("Every 30 minutes"));
+ gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), _("Every hour"));
+ gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), _("Every day"));
+ gtk_widget_show (combo);
+
+ button2 = gtk_check_button_new_with_mnemonic (_("_Random order"));
+ g_object_bind_property (button, "active", button2, "sensitive", G_BINDING_SYNC_CREATE);
+ gtk_box_pack_start (GTK_BOX (hbox), button2, FALSE, TRUE, 0);
+ gtk_widget_show (button2);
+}
+
+
+
+static void
+thunar_desktop_preferences_dialog_finalize (GObject *object)
+{
+ ThunarDesktopPreferencesDialog *dialog = THUNAR_DESKTOP_PREFERENCES_DIALOG (object);
+
+ g_free (dialog->background_prop);
+
+ (*G_OBJECT_CLASS (thunar_desktop_preferences_dialog_parent_class)->finalize) (object);
+}
+
+
+
+static void
+thunar_desktop_preferences_dialog_realize (GtkWidget *widget)
+{
+ ThunarDesktopPreferencesDialog *dialog = THUNAR_DESKTOP_PREFERENCES_DIALOG (widget);
+
+ GTK_WIDGET_CLASS (thunar_desktop_preferences_dialog_parent_class)->realize (widget);
+
+ thunar_desktop_preferences_dialog_update (dialog);
+}
+
+
+
+static void
+thunar_desktop_preferences_dialog_screen_changed (GtkWidget *widget,
+ GdkScreen *old_screen)
+{
+ ThunarDesktopPreferencesDialog *dialog = THUNAR_DESKTOP_PREFERENCES_DIALOG (widget);
+
+ thunar_desktop_preferences_dialog_update (dialog);
+}
+
+
+
+static void
+thunar_desktop_preferences_dialog_response (GtkDialog *dialog,
+ gint response)
+{
+ if (G_UNLIKELY (response == GTK_RESPONSE_HELP))
+ {
+ /* open the preferences section of the user manual */
+ xfce_dialog_show_help (GTK_WINDOW (dialog), "thunar",
+ "desktop", NULL);
+ }
+ else
+ {
+ /* close the preferences dialog */
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+ }
+}
+
+
+
+static void
+thunar_desktop_preferences_dialog_update (ThunarDesktopPreferencesDialog *dialog)
+{
+ gchar prop[128];
+ gchar *uri;
+ ThunarFile *file;
+ GFile *gfile;
+ ThunarFile *file_parent;
+ GList fake;
+
+ /* update the base property */
+ thunar_desktop_preferences_dialog_background_prop (dialog);
+
+ g_snprintf (prop, sizeof (prop), "%s/uri", dialog->background_prop);
+ uri = xfconf_channel_get_string (dialog->settings, prop, DATADIR "/backgrounds/xfce/xfce-blue.jpg");
+ gfile = g_file_new_for_commandline_arg (uri);
+ g_free (uri);
+
+ /* select the file in the view */
+ file = thunar_file_get (gfile, NULL);
+ if (file != NULL)
+ {
+ file_parent = thunar_file_get_parent (file, NULL);
+ if (file_parent != NULL)
+ {
+ /* set view of the directory */
+ thunar_navigator_set_current_directory (THUNAR_NAVIGATOR (dialog->view), file_parent);
+ gtk_file_chooser_set_current_folder_file (GTK_FILE_CHOOSER (dialog->folder_chooser),
+ thunar_file_get_file (file_parent), NULL);
+ g_object_unref (file_parent);
+
+ /* create a fake list and select the file */
+ fake.prev = fake.next = NULL;
+ fake.data = file;
+ thunar_component_set_selected_files (THUNAR_COMPONENT (dialog->view), &fake);
+ }
+
+ g_object_unref (file);
+ }
+}
+
+
+
+static void
+thunar_desktop_preferences_dialog_background_changed (ThunarDesktopPreferencesDialog *dialog)
+{
+ GList *files;
+ ThunarFile *file;
+ gchar *uri;
+ gchar *prop;
+
+ /* get the selected file */
+ files = thunar_component_get_selected_files (THUNAR_COMPONENT (dialog->view));
+ _thunar_assert (files == NULL || files->next == NULL);
+ file = g_list_nth_data (files, 0);
+
+ if (file != NULL)
+ {
+ /* save uri */
+ uri = thunar_file_dup_uri (file);
+ prop = g_strdup_printf ("%s/uri", dialog->background_prop);
+ xfconf_channel_set_string (dialog->settings, prop, uri);
+ g_free (uri);
+ g_free (prop);
+ }
+}
+
+
+
+static void
+thunar_desktop_preferences_dialog_background_prop (ThunarDesktopPreferencesDialog *dialog)
+{
+ GdkScreen *screen;
+ gint monitor_num;
+ gchar *monitor_name;
+
+ g_free (dialog->background_prop);
+
+ screen = gtk_window_get_screen (GTK_WINDOW (dialog));
+ monitor_num = gdk_screen_get_monitor_at_window (screen, gtk_widget_get_window (GTK_WIDGET (dialog)));
+ monitor_name = gdk_screen_get_monitor_plug_name (screen, monitor_num);
+
+ if (monitor_name == NULL)
+ monitor_name = g_strdup_printf ("monitor-%d", monitor_num);
+
+ dialog->background_prop = g_strdup_printf ("/background/screen-%d/%s",
+ gdk_screen_get_number (screen),
+ monitor_name);
+
+ g_free (monitor_name);
+}
+
+
+
+static void
+thunar_desktop_preferences_dialog_folder_changed (ThunarDesktopPreferencesDialog *dialog)
+{
+ GFile *gfile;
+ ThunarFile *current_directory;
+
+ gfile = gtk_file_chooser_get_current_folder_file (GTK_FILE_CHOOSER (dialog->folder_chooser));
+ if (G_LIKELY (gfile != NULL))
+ {
+ current_directory = thunar_file_get (gfile, NULL);
+ g_object_unref (gfile);
+
+ thunar_navigator_set_current_directory (THUNAR_NAVIGATOR (dialog->view), current_directory);
+ g_object_unref (current_directory);
+ }
+}
+
+
+
+/**
+ * thunar_desktop_preferences_dialog_new:
+ * @parent : a #GtkWindow or %NULL.
+ *
+ * Allocates a new #ThunarDesktopPreferencesDialog widget.
+ *
+ * Return value: the newly allocated #ThunarDesktopPreferencesDialog.
+ **/
+GtkWidget *
+thunar_desktop_preferences_dialog_new (GtkWindow *parent)
+{
+ return g_object_new (THUNAR_TYPE_DESKTOP_PREFERENCES_DIALOG,
+ "screen", gtk_window_get_screen (parent), NULL);
+}
+
diff --git a/thunar/thunar-desktop-preferences-dialog.h b/thunar/thunar-desktop-preferences-dialog.h
new file mode 100644
index 0000000..12b990b
--- /dev/null
+++ b/thunar/thunar-desktop-preferences-dialog.h
@@ -0,0 +1,42 @@
+/*-
+ * Copyright (c) 2013 Nick Schermer <nick at xfce.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __THUNAR_DESKTOP_PREFERENCES_DIALOG_H__
+#define __THUNAR_DESKTOP_PREFERENCES_DIALOG_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS;
+
+typedef struct _ThunarDesktopPreferencesDialogClass ThunarDesktopPreferencesDialogClass;
+typedef struct _ThunarDesktopPreferencesDialog ThunarDesktopPreferencesDialog;
+
+#define THUNAR_TYPE_DESKTOP_PREFERENCES_DIALOG (thunar_desktop_preferences_dialog_get_type ())
+#define THUNAR_DESKTOP_PREFERENCES_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_TYPE_DESKTOP_PREFERENCES_DIALOG, ThunarDesktopPreferencesDialog))
+#define THUNAR_DESKTOP_PREFERENCES_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), THUNAR_TYPE_DESKTOP_PREFERENCES_DIALOG, ThunarDesktopPreferencesDialogClass))
+#define THUNAR_IS_DESKTOP_PREFERENCES_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THUNAR_TYPE_DESKTOP_PREFERENCES_DIALOG))
+#define THUNAR_IS_DESKTOP_PREFERENCES_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), THUNAR_TYPE_DESKTOP_PREFERENCES_DIALOG))
+#define THUNAR_DESKTOP_PREFERENCES_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_TYPE_DESKTOP_PREFERENCES_DIALOG, ThunarDesktopPreferencesDialogClass))
+
+GType thunar_desktop_preferences_dialog_get_type (void) G_GNUC_CONST;
+
+GtkWidget *thunar_desktop_preferences_dialog_new (GtkWindow *parent) G_GNUC_MALLOC;
+
+G_END_DECLS;
+
+#endif /* !__THUNAR_DESKTOP_PREFERENCES_DIALOG_H__ */
diff --git a/thunar/thunar-desktop-window.c b/thunar/thunar-desktop-window.c
new file mode 100644
index 0000000..dfa48da
--- /dev/null
+++ b/thunar/thunar-desktop-window.c
@@ -0,0 +1,260 @@
+/*-
+ * Copyright (c) 2006 Benedikt Meurer <benny at xfce.org>
+ * Copyright (c) 2012 Nick Schermer <nick at xfce.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <thunar/thunar-private.h>
+#include <thunar/thunar-desktop-window.h>
+#include <thunar/thunar-desktop-background.h>
+#include <thunar/thunar-desktop-preferences-dialog.h>
+
+#ifdef GDK_WINDOWING_X11
+#include <gdk/gdkx.h>
+#endif
+
+
+
+static void thunar_desktop_window_size_request (GtkWidget *widget,
+ GtkRequisition *requisition);
+static void thunar_desktop_window_realize (GtkWidget *widget);
+static void thunar_desktop_window_unrealize (GtkWidget *widget);
+static gboolean thunar_desktop_window_expose_event (GtkWidget *widget,
+ GdkEventExpose *event);
+static gboolean thunar_desktop_window_button_press_event (GtkWidget *widget,
+ GdkEventButton *event);
+
+
+
+struct _ThunarDesktopWindowClass
+{
+ GtkWindowClass __parent__;
+};
+
+struct _ThunarDesktopWindow
+{
+ GtkWindow __parent__;
+
+ ThunarDesktopBackground *background;
+};
+
+
+
+G_DEFINE_TYPE (ThunarDesktopWindow, thunar_desktop_window, GTK_TYPE_WINDOW)
+
+
+
+static void
+thunar_desktop_window_class_init (ThunarDesktopWindowClass *klass)
+{
+ GtkWidgetClass *gtkwidget_class;
+
+ gtkwidget_class = GTK_WIDGET_CLASS (klass);
+ gtkwidget_class->size_request = thunar_desktop_window_size_request;
+ gtkwidget_class->realize = thunar_desktop_window_realize;
+ gtkwidget_class->unrealize = thunar_desktop_window_unrealize;
+ gtkwidget_class->expose_event = thunar_desktop_window_expose_event;
+ gtkwidget_class->button_press_event = thunar_desktop_window_button_press_event;
+}
+
+
+
+static void
+thunar_desktop_window_init (ThunarDesktopWindow *window)
+{
+ gtk_widget_add_events (GTK_WIDGET (window),
+ GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
+
+ gtk_window_move (GTK_WINDOW (window), 0, 0);
+ gtk_window_set_type_hint (GTK_WINDOW (window), GDK_WINDOW_TYPE_HINT_DESKTOP);
+ gtk_widget_set_double_buffered (GTK_WIDGET (window), FALSE);
+}
+
+
+
+static void
+thunar_desktop_window_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ GdkScreen *screen = gtk_widget_get_screen (widget);
+
+ requisition->width = gdk_screen_get_width (screen);
+ requisition->height = gdk_screen_get_height (screen);
+}
+
+
+
+static void
+thunar_desktop_window_screen_changed (GdkScreen *screen,
+ ThunarDesktopWindow *window)
+{
+ GdkWindow *gdk_window;
+
+ /* release background */
+ if (window->background != NULL)
+ {
+ g_object_unref (G_OBJECT (window->background));
+ window->background = NULL;
+ }
+
+ /* allocate bg and set it on the window */
+ gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
+ window->background = thunar_desktop_background_new (gdk_window);
+}
+
+
+
+static void
+thunar_desktop_window_realize (GtkWidget *widget)
+{
+ GdkScreen *screen;
+ GdkWindow *root;
+ Window xid;
+
+ GTK_WIDGET_CLASS (thunar_desktop_window_parent_class)->realize (widget);
+
+ screen = gtk_widget_get_screen (widget);
+ root = gdk_screen_get_root_window (screen);
+
+ /* tell the root window that we have a new "desktop" window */
+ xid = GDK_DRAWABLE_XID (gtk_widget_get_window (widget));
+ gdk_property_change (root,
+ gdk_atom_intern ("NAUTILUS_DESKTOP_WINDOW_ID", FALSE),
+ gdk_atom_intern ("WINDOW", FALSE), 32,
+ GDK_PROP_MODE_REPLACE, (gpointer) &xid, 1);
+ gdk_property_change (root,
+ gdk_atom_intern ("XFCE_DESKTOP_WINDOW", FALSE),
+ gdk_atom_intern ("WINDOW", FALSE), 32,
+ GDK_PROP_MODE_REPLACE, (gpointer) &xid, 1);
+
+ /* watch screen changes */
+ g_signal_connect_swapped (G_OBJECT (screen), "size-changed",
+ G_CALLBACK (thunar_desktop_window_screen_changed), widget);
+ g_signal_connect_swapped (G_OBJECT (screen), "monitors-changed",
+ G_CALLBACK (thunar_desktop_window_screen_changed), widget);
+
+ /* prepare bg */
+ thunar_desktop_window_screen_changed (screen, THUNAR_DESKTOP_WINDOW (widget));
+}
+
+
+
+static void
+thunar_desktop_window_unrealize (GtkWidget *widget)
+{
+ ThunarDesktopWindow *window = THUNAR_DESKTOP_WINDOW (widget);
+ GdkScreen *screen;
+ GdkWindow *root;
+
+ /* drop background */
+ if (window->background != NULL)
+ {
+ g_object_unref (G_OBJECT (window->background));
+ window->background = NULL;
+ }
+ gdk_window_set_back_pixmap (gtk_widget_get_window (widget), NULL, FALSE);
+
+ /* disconnect the XRandR support handler */
+ screen = gtk_widget_get_screen (widget);
+ g_signal_handlers_disconnect_by_func (G_OBJECT (screen),
+ thunar_desktop_window_screen_changed, widget);
+
+ /* unset root window properties */
+ root = gdk_screen_get_root_window (screen);
+ gdk_property_delete (root, gdk_atom_intern ("NAUTILUS_DESKTOP_WINDOW_ID", FALSE));
+ gdk_property_delete (root, gdk_atom_intern ("XFCE_DESKTOP_WINDOW", FALSE));
+
+ GTK_WIDGET_CLASS (thunar_desktop_window_parent_class)->unrealize (widget);
+}
+
+
+
+static gboolean
+thunar_desktop_window_expose_event (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ /* leave on multiple events */
+ if (event->count != 0)
+ return FALSE;
+
+ /* paint background */
+ gdk_window_clear_area (gtk_widget_get_window (widget),
+ event->area.x, event->area.y,
+ event->area.width, event->area.height);
+
+ return FALSE;
+}
+
+
+
+static gboolean
+thunar_desktop_window_button_press_event (GtkWidget *widget,
+ GdkEventButton *event)
+{
+ ThunarDesktopWindow *window = THUNAR_DESKTOP_WINDOW (widget);
+ GtkWidget *dialog;
+
+ if (event->type == GDK_BUTTON_PRESS)
+ {
+ if (event->button == 3
+ || (event->button == 1 && (event->state & GDK_SHIFT_MASK) != 0))
+ {
+ dialog = thunar_desktop_preferences_dialog_new (GTK_WINDOW (window));
+ gtk_widget_show (dialog);
+ }
+ }
+
+ return FALSE;
+}
+
+
+
+/**
+ * thunar_desktop_window_new:
+ *
+ * Allocates a new #ThunarDesktopWindow instance.
+ *
+ * Return value: the newly allocated #ThunarDesktopWindow.
+ **/
+GtkWidget*
+thunar_desktop_window_new (void)
+{
+ return thunar_desktop_window_new_with_screen (gdk_screen_get_default ());
+}
+
+
+
+/**
+ * thunar_desktop_window_new_with_screen:
+ * @screen : a #GdkScreen.
+ *
+ * Allocates a new #ThunarDesktopWindow instance and
+ * associates it with the given @screen.
+ *
+ * Return value: the newly allocated #ThunarDesktopWindow.
+ **/
+GtkWidget*
+thunar_desktop_window_new_with_screen (GdkScreen *screen)
+{
+ g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
+ return g_object_new (THUNAR_TYPE_DESKTOP_WINDOW,
+ "screen", screen,
+ NULL);
+}
diff --git a/thunar/thunar-desktop-window.h b/thunar/thunar-desktop-window.h
new file mode 100644
index 0000000..bcfb1d3
--- /dev/null
+++ b/thunar/thunar-desktop-window.h
@@ -0,0 +1,44 @@
+/*-
+ * Copyright (c) 2006 Benedikt Meurer <benny at xfce.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __THUNAR_DESKTOP_WINDOW_H__
+#define __THUNAR_DESKTOP_WINDOW_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+typedef struct _ThunarDesktopWindowClass ThunarDesktopWindowClass;
+typedef struct _ThunarDesktopWindow ThunarDesktopWindow;
+
+#define THUNAR_TYPE_DESKTOP_WINDOW (thunar_desktop_window_get_type ())
+#define THUNAR_DESKTOP_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_TYPE_DESKTOP_WINDOW, ThunarDesktopWindow))
+#define THUNAR_DESKTOP_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), THUNAR_TYPE_DESKTOP_WINDOW, ThunarDesktopWindowClass))
+#define THUNAR_IS_DESKTOP_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THUNAR_TYPE_DESKTOP_WINDOW))
+#define THUNAR_IS_DESKTOP_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), THUNAR_TYPE_DESKTOP_WINDOW))
+#define THUNAR_DESKTOP_WINDOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_TYPE_DESKTOP_WINDOW, ThunarDesktopWindowClass))
+
+GType thunar_desktop_window_get_type (void) G_GNUC_CONST;
+
+GtkWidget *thunar_desktop_window_new (void);
+
+GtkWidget *thunar_desktop_window_new_with_screen (GdkScreen *screen);
+
+G_END_DECLS
+
+#endif /* !__THUNAR_DESKTOP_WINDOW_H__ */
diff --git a/thunar/thunar-enum-types.c b/thunar/thunar-enum-types.c
index 92dcf09..0eed66e 100644
--- a/thunar/thunar-enum-types.c
+++ b/thunar/thunar-enum-types.c
@@ -251,26 +251,26 @@ thunar_icon_size_from_zoom_level (const GValue *src_value,
GType
thunar_job_response_get_type (void)
{
- static GType type = G_TYPE_INVALID;
+ static GType type = G_TYPE_INVALID;
if (G_UNLIKELY (type == G_TYPE_INVALID))
{
- static const GFlagsValue values[] =
+ static const GFlagsValue values[] =
{
- { THUNAR_JOB_RESPONSE_YES, "THUNAR_JOB_RESPONSE_YES", "yes" },
- { THUNAR_JOB_RESPONSE_YES_ALL, "THUNAR_JOB_RESPONSE_YES_ALL", "yes-all" },
- { THUNAR_JOB_RESPONSE_NO, "THUNAR_JOB_RESPONSE_NO", "no" },
- { THUNAR_JOB_RESPONSE_CANCEL, "THUNAR_JOB_RESPONSE_CANCEL", "cancel" },
- { THUNAR_JOB_RESPONSE_NO_ALL, "THUNAR_JOB_RESPONSE_NO_ALL", "no-all" },
- { THUNAR_JOB_RESPONSE_RETRY, "THUNAR_JOB_RESPONSE_RETRY", "retry" },
- { THUNAR_JOB_RESPONSE_FORCE, "THUNAR_JOB_RESPONSE_FORCE", "force" },
- { 0, NULL, NULL }
- };
-
- type = g_flags_register_static (I_("ThunarJobResponse"), values);
+ { THUNAR_JOB_RESPONSE_YES, "THUNAR_JOB_RESPONSE_YES", "yes" },
+ { THUNAR_JOB_RESPONSE_YES_ALL, "THUNAR_JOB_RESPONSE_YES_ALL", "yes-all" },
+ { THUNAR_JOB_RESPONSE_NO, "THUNAR_JOB_RESPONSE_NO", "no" },
+ { THUNAR_JOB_RESPONSE_CANCEL, "THUNAR_JOB_RESPONSE_CANCEL", "cancel" },
+ { THUNAR_JOB_RESPONSE_NO_ALL, "THUNAR_JOB_RESPONSE_NO_ALL", "no-all" },
+ { THUNAR_JOB_RESPONSE_RETRY, "THUNAR_JOB_RESPONSE_RETRY", "retry" },
+ { THUNAR_JOB_RESPONSE_FORCE, "THUNAR_JOB_RESPONSE_FORCE", "force" },
+ { 0, NULL, NULL }
+ };
+
+ type = g_flags_register_static (I_("ThunarJobResponse"), values);
}
- return type;
+ return type;
}
@@ -278,31 +278,80 @@ thunar_job_response_get_type (void)
GType
thunar_file_mode_get_type (void)
{
- static GType type = G_TYPE_INVALID;
+ static GType type = G_TYPE_INVALID;
- if (type == G_TYPE_INVALID)
+ if (type == G_TYPE_INVALID)
{
- static const GFlagsValue values[] =
+ static const GFlagsValue values[] =
{
- { THUNAR_FILE_MODE_SUID, "THUNAR_FILE_MODE_SUID", "suid" },
- { THUNAR_FILE_MODE_SGID, "THUNAR_FILE_MODE_SGID", "sgid" },
- { THUNAR_FILE_MODE_STICKY, "THUNAR_FILE_MODE_STICKY", "sticky" },
- { THUNAR_FILE_MODE_USR_ALL, "THUNAR_FILE_MODE_USR_ALL", "usr-all" },
- { THUNAR_FILE_MODE_USR_READ, "THUNAR_FILE_MODE_USR_READ", "usr-read" },
- { THUNAR_FILE_MODE_USR_WRITE, "THUNAR_FILE_MODE_USR_WRITE", "usr-write" },
- { THUNAR_FILE_MODE_USR_EXEC, "THUNAR_FILE_MODE_USR_EXEC", "usr-exec" },
- { THUNAR_FILE_MODE_GRP_ALL, "THUNAR_FILE_MODE_GRP_ALL", "grp-all" },
- { THUNAR_FILE_MODE_GRP_READ, "THUNAR_FILE_MODE_GRP_READ", "grp-read" },
- { THUNAR_FILE_MODE_GRP_WRITE, "THUNAR_FILE_MODE_GRP_WRITE", "grp-write" },
- { THUNAR_FILE_MODE_GRP_EXEC, "THUNAR_FILE_MODE_GRP_EXEC", "grp-exec" },
- { THUNAR_FILE_MODE_OTH_ALL, "THUNAR_FILE_MODE_OTH_ALL", "oth-all" },
- { THUNAR_FILE_MODE_OTH_READ, "THUNAR_FILE_MODE_OTH_READ", "oth-read" },
- { THUNAR_FILE_MODE_OTH_WRITE, "THUNAR_FILE_MODE_OTH_WRITE", "oth-write" },
- { THUNAR_FILE_MODE_OTH_EXEC, "THUNAR_FILE_MODE_OTH_EXEC", "oth-exec" },
- { 0, NULL, NULL }
- };
-
+ { THUNAR_FILE_MODE_SUID, "THUNAR_FILE_MODE_SUID", "suid" },
+ { THUNAR_FILE_MODE_SGID, "THUNAR_FILE_MODE_SGID", "sgid" },
+ { THUNAR_FILE_MODE_STICKY, "THUNAR_FILE_MODE_STICKY", "sticky" },
+ { THUNAR_FILE_MODE_USR_ALL, "THUNAR_FILE_MODE_USR_ALL", "usr-all" },
+ { THUNAR_FILE_MODE_USR_READ, "THUNAR_FILE_MODE_USR_READ", "usr-read" },
+ { THUNAR_FILE_MODE_USR_WRITE, "THUNAR_FILE_MODE_USR_WRITE", "usr-write" },
+ { THUNAR_FILE_MODE_USR_EXEC, "THUNAR_FILE_MODE_USR_EXEC", "usr-exec" },
+ { THUNAR_FILE_MODE_GRP_ALL, "THUNAR_FILE_MODE_GRP_ALL", "grp-all" },
+ { THUNAR_FILE_MODE_GRP_READ, "THUNAR_FILE_MODE_GRP_READ", "grp-read" },
+ { THUNAR_FILE_MODE_GRP_WRITE, "THUNAR_FILE_MODE_GRP_WRITE", "grp-write" },
+ { THUNAR_FILE_MODE_GRP_EXEC, "THUNAR_FILE_MODE_GRP_EXEC", "grp-exec" },
+ { THUNAR_FILE_MODE_OTH_ALL, "THUNAR_FILE_MODE_OTH_ALL", "oth-all" },
+ { THUNAR_FILE_MODE_OTH_READ, "THUNAR_FILE_MODE_OTH_READ", "oth-read" },
+ { THUNAR_FILE_MODE_OTH_WRITE, "THUNAR_FILE_MODE_OTH_WRITE", "oth-write" },
+ { THUNAR_FILE_MODE_OTH_EXEC, "THUNAR_FILE_MODE_OTH_EXEC", "oth-exec" },
+ { 0, NULL, NULL }
+ };
+
type = g_flags_register_static ("ThunarFileMode", values);
}
- return type;
+ return type;
+}
+
+
+
+GType
+thunar_background_style_get_type (void)
+{
+ static GType type = G_TYPE_INVALID;
+
+ if (type == G_TYPE_INVALID)
+ {
+ static const GEnumValue values[] =
+ {
+ { THUNAR_BACKGROUND_STYLE_NONE, "THUNAR_BACKGROUND_STYLE_NONE", N_ ("None") },
+ { THUNAR_BACKGROUND_STYLE_TILED, "THUNAR_BACKGROUND_STYLE_TILED", N_ ("Titled") },
+ { THUNAR_BACKGROUND_STYLE_CENTERED, "THUNAR_BACKGROUND_STYLE_CENTERED", N_ ("Centered") },
+ { THUNAR_BACKGROUND_STYLE_STRETCHED, "THUNAR_BACKGROUND_STYLE_STRETCHED", N_ ("Stretched") },
+ { THUNAR_BACKGROUND_STYLE_SCALED, "THUNAR_BACKGROUND_STYLE_SCALED", N_ ("Scaled") },
+ { THUNAR_BACKGROUND_STYLE_ZOOMED, "THUNAR_BACKGROUND_STYLE_ZOOMED", N_ ("Zoomed") },
+ { THUNAR_BACKGROUND_STYLE_SPANNED, "THUNAR_BACKGROUND_STYLE_SPANNED", N_ ("Spanned") },
+ { 0, NULL, NULL }
+ };
+
+ type = g_enum_register_static ("ThunarBackgroundStyle", values);
+ }
+ return type;
+}
+
+
+
+GType
+thunar_background_color_style_get_type (void)
+{
+ static GType type = G_TYPE_INVALID;
+
+ if (type == G_TYPE_INVALID)
+ {
+ static const GEnumValue values[] =
+ {
+ { THUNAR_BACKGROUND_COLOR_STYLE_SOLID, "THUNAR_BACKGROUND_COLOR_STYLE_SOLID", N_ ("Solid") },
+ { THUNAR_BACKGROUND_COLOR_STYLE_HORIZONTAL, "THUNAR_BACKGROUND_COLOR_STYLE_HORIZONTAL", N_ ("Horizontal") },
+ { THUNAR_BACKGROUND_COLOR_STYLE_VERTICAL, "THUNAR_BACKGROUND_COLOR_STYLE_VERTICAL", N_ ("Vertical") },
+ { THUNAR_BACKGROUND_COLOR_STYLE_RADIAL, "THUNAR_BACKGROUND_COLOR_STYLE_RADIAL", N_ ("Radial") },
+ { 0, NULL, NULL }
+ };
+
+ type = g_enum_register_static ("ThunarBackgroundColorStyle", values);
+ }
+ return type;
}
diff --git a/thunar/thunar-enum-types.h b/thunar/thunar-enum-types.h
index c372436..eb426cb 100644
--- a/thunar/thunar-enum-types.h
+++ b/thunar/thunar-enum-types.h
@@ -268,6 +268,45 @@ typedef enum /*< flags >*/
GType thunar_file_mode_get_type (void) G_GNUC_CONST;
+
+#define THUNAR_TYPE_BACKGROUND_STYLE (thunar_background_style_get_type ())
+
+/**
+ * ThunarBackgroundStyle:
+ *
+ * Transformations of the background image on the background
+ **/
+typedef enum /*< flags >*/
+{
+ THUNAR_BACKGROUND_STYLE_NONE,
+ THUNAR_BACKGROUND_STYLE_TILED, /* no scaling, fill screen from 0,0 */
+ THUNAR_BACKGROUND_STYLE_CENTERED, /* center on monitor once, no resizing */
+ THUNAR_BACKGROUND_STYLE_STRETCHED, /* scale to fill screen */
+ THUNAR_BACKGROUND_STYLE_SCALED, /* scale to monitor, center */
+ THUNAR_BACKGROUND_STYLE_ZOOMED, /* scale to monitor, crop + center */
+ THUNAR_BACKGROUND_STYLE_SPANNED, /* scale to fit screen */
+} ThunarBackgroundStyle;
+
+GType thunar_background_style_get_type (void) G_GNUC_CONST;
+
+
+#define THUNAR_TYPE_BACKGROUND_COLOR_STYLE (thunar_background_color_style_get_type ())
+
+/**
+ * ThunarBackgroundColorStyle:
+ *
+ * Fill of the background color
+ **/
+typedef enum /*< flags >*/
+{
+ THUNAR_BACKGROUND_COLOR_STYLE_SOLID,
+ THUNAR_BACKGROUND_COLOR_STYLE_HORIZONTAL,
+ THUNAR_BACKGROUND_COLOR_STYLE_VERTICAL,
+ THUNAR_BACKGROUND_COLOR_STYLE_RADIAL,
+} ThunarBackgroundColorStyle;
+
+GType thunar_background_color_style_get_type (void) G_GNUC_CONST;
+
G_END_DECLS;
#endif /* !__THUNAR_ENUM_TYPES_H__ */
diff --git a/thunar/thunar-gtk-extensions.c b/thunar/thunar-gtk-extensions.c
index 1938a95..f158a33 100644
--- a/thunar/thunar-gtk-extensions.c
+++ b/thunar/thunar-gtk-extensions.c
@@ -199,8 +199,11 @@ thunar_gtk_ui_manager_get_action_by_name (GtkUIManager *ui_manager,
GtkAction *action;
GList *lp;
- _thunar_return_val_if_fail (GTK_IS_UI_MANAGER (ui_manager), NULL);
+ _thunar_return_val_if_fail (ui_manager == NULL || GTK_IS_UI_MANAGER (ui_manager), NULL);
_thunar_return_val_if_fail (action_name != NULL, NULL);
+
+ if (ui_manager == NULL)
+ return NULL;
/* check all action groups associated with the ui manager */
for (lp = gtk_ui_manager_get_action_groups (ui_manager); lp != NULL; lp = lp->next)
diff --git a/thunar/thunar-list-model.c b/thunar/thunar-list-model.c
index 43acdc9..9cdd1c3 100644
--- a/thunar/thunar-list-model.c
+++ b/thunar/thunar-list-model.c
@@ -227,6 +227,9 @@ struct _ThunarListModel
gboolean sort_folders_first : 1;
gint sort_sign; /* 1 = ascending, -1 descending */
ThunarSortFunc sort_func;
+
+ ThunarListModelVisibleFunc visible_func;
+ gpointer visible_data;
};
@@ -1222,9 +1225,15 @@ thunar_list_model_files_added (ThunarFolder *folder,
/* process all added files */
for (lp = files; lp != NULL; lp = lp->next)
{
+ _thunar_return_if_fail (THUNAR_IS_FILE (lp->data));
+
+ /* skip files that do not pass the visible function */
+ if (store->visible_func != NULL
+ && !store->visible_func (lp->data, store->visible_data))
+ continue;
+
/* take a reference on that file */
file = g_object_ref (G_OBJECT (lp->data));
- _thunar_return_if_fail (THUNAR_IS_FILE (file));
/* check if the file should be hidden */
if (!store->show_hidden && thunar_file_is_hidden (file))
@@ -1821,6 +1830,24 @@ thunar_list_model_set_folder (ThunarListModel *store,
/**
+ * thunar_list_model_set_visible_func:
+ * @store: a #ThunarListModel.
+ * @func : filter function.
+ * @data: user data.
+ **/
+void
+thunar_list_model_set_visible_func (ThunarListModel *store,
+ ThunarListModelVisibleFunc func,
+ gpointer data)
+{
+ _thunar_return_if_fail (THUNAR_IS_LIST_MODEL (store));
+ store->visible_func = func;
+ store->visible_data = data;
+}
+
+
+
+/**
* thunar_list_model_get_folders_first:
* @store : a #ThunarListModel.
*
diff --git a/thunar/thunar-list-model.h b/thunar/thunar-list-model.h
index 9392a02..57804bf 100644
--- a/thunar/thunar-list-model.h
+++ b/thunar/thunar-list-model.h
@@ -27,6 +27,10 @@ G_BEGIN_DECLS;
typedef struct _ThunarListModelClass ThunarListModelClass;
typedef struct _ThunarListModel ThunarListModel;
+/* filter for removing files before they are added into the model */
+typedef gboolean (*ThunarListModelVisibleFunc) (ThunarFile *file,
+ gpointer data);
+
#define THUNAR_TYPE_LIST_MODEL (thunar_list_model_get_type ())
#define THUNAR_LIST_MODEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_TYPE_LIST_MODEL, ThunarListModel))
#define THUNAR_LIST_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), THUNAR_TYPE_LIST_MODEL, ThunarListModelClass))
@@ -42,6 +46,10 @@ ThunarFolder *thunar_list_model_get_folder (ThunarListModel *sto
void thunar_list_model_set_folder (ThunarListModel *store,
ThunarFolder *folder);
+void thunar_list_model_set_visible_func (ThunarListModel *store,
+ ThunarListModelVisibleFunc func,
+ gpointer data);
+
void thunar_list_model_set_folders_first (ThunarListModel *store,
gboolean folders_first);
diff --git a/thunar/thunar-standard-view.c b/thunar/thunar-standard-view.c
index 0dc3a68..9cb1f67 100644
--- a/thunar/thunar-standard-view.c
+++ b/thunar/thunar-standard-view.c
@@ -731,6 +731,7 @@ thunar_standard_view_constructor (GType type,
GtkSortType sort_order;
GtkWidget *view;
GObject *object;
+ const gchar *zoom_level_property_name;
/* let the GObject constructor create the instance */
object = G_OBJECT_CLASS (thunar_standard_view_parent_class)->constructor (type,
@@ -741,11 +742,15 @@ thunar_standard_view_constructor (GType type,
standard_view = THUNAR_STANDARD_VIEW (object);
/* setup the default zoom-level, determined from the "last-<view>-zoom-level" preference */
- g_object_get (G_OBJECT (standard_view->preferences), THUNAR_STANDARD_VIEW_GET_CLASS (standard_view)->zoom_level_property_name, &zoom_level, NULL);
- thunar_view_set_zoom_level (THUNAR_VIEW (standard_view), zoom_level);
+ zoom_level_property_name = THUNAR_STANDARD_VIEW_GET_CLASS (standard_view)->zoom_level_property_name;
+ if (G_LIKELY (zoom_level_property_name != NULL))
+ {
+ g_object_get (G_OBJECT (standard_view->preferences), zoom_level_property_name, &zoom_level, NULL);
+ thunar_view_set_zoom_level (THUNAR_VIEW (standard_view), zoom_level);
- /* save the "zoom-level" as "last-<view>-zoom-level" whenever the user changes the zoom level */
- g_object_bind_property (object, "zoom-level", G_OBJECT (standard_view->preferences), THUNAR_STANDARD_VIEW_GET_CLASS (standard_view)->zoom_level_property_name, G_BINDING_DEFAULT);
+ /* save the "zoom-level" as "last-<view>-zoom-level" whenever the user changes the zoom level */
+ g_object_bind_property (object, "zoom-level", G_OBJECT (standard_view->preferences), zoom_level_property_name, G_BINDING_DEFAULT);
+ }
/* determine the real view widget (treeview or iconview) */
view = GTK_BIN (object)->child;
@@ -1687,6 +1692,9 @@ thunar_standard_view_reset_zoom_level (ThunarView *view)
/* determine the default zoom level from the preferences */
property_name = THUNAR_STANDARD_VIEW_GET_CLASS (standard_view)->zoom_level_property_name;
+ if (property_name == NULL)
+ return;
+
pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (standard_view->preferences), property_name);
g_value_init (&value, THUNAR_TYPE_ZOOM_LEVEL);
g_param_value_set_default (pspec, &value);
@@ -4145,6 +4153,9 @@ thunar_standard_view_context_menu (ThunarStandardView *standard_view,
_thunar_return_if_fail (THUNAR_IS_STANDARD_VIEW (standard_view));
+ if (standard_view->ui_manager == NULL)
+ return;
+
/* merge the custom menu actions for the selected items */
selected_items = (*THUNAR_STANDARD_VIEW_GET_CLASS (standard_view)->get_selected_items) (standard_view);
thunar_standard_view_merge_custom_actions (standard_view, selected_items);
More information about the Xfce4-commits
mailing list