diff options
author | William Jon McCann <mccann@jhu.edu> | 2007-09-12 20:48:19 +0000 |
---|---|---|
committer | William Jon McCann <mccann@src.gnome.org> | 2007-09-12 20:48:19 +0000 |
commit | 128530db21a5c08c9afa2a285bf2ad114e623214 (patch) | |
tree | bd9df950186e9d009dd2cbdd11b71251b22c3f25 | |
parent | 4e7b2b84f492f576c3944f35d3d1dff835b09bb1 (diff) | |
download | gdm-128530db21a5c08c9afa2a285bf2ad114e623214.tar.gz |
Added cut-n-paste lib.
2007-09-12 William Jon McCann <mccann@jhu.edu>
* gui/simple-greeter/Makefile.am:
* gui/simple-greeter/libbackground:
Added cut-n-paste lib.
svn path=/branches/mccann-gobject/; revision=5251
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | gui/simple-greeter/Makefile.am | 3 | ||||
-rw-r--r-- | gui/simple-greeter/libbackground/ChangeLog | 517 | ||||
-rw-r--r-- | gui/simple-greeter/libbackground/Makefile.am | 13 | ||||
-rw-r--r-- | gui/simple-greeter/libbackground/applier.c | 1699 | ||||
-rw-r--r-- | gui/simple-greeter/libbackground/applier.h | 76 | ||||
-rw-r--r-- | gui/simple-greeter/libbackground/preferences.c | 510 | ||||
-rw-r--r-- | gui/simple-greeter/libbackground/preferences.h | 108 | ||||
-rw-r--r-- | gui/simple-greeter/libnotificationarea/na-marshal.c | 165 | ||||
-rw-r--r-- | gui/simple-greeter/libnotificationarea/na-marshal.h | 36 |
10 files changed, 2932 insertions, 201 deletions
@@ -1,6 +1,12 @@ 2007-09-12 William Jon McCann <mccann@jhu.edu> * gui/simple-greeter/Makefile.am: + * gui/simple-greeter/libbackground: + Added cut-n-paste lib. + +2007-09-12 William Jon McCann <mccann@jhu.edu> + + * gui/simple-greeter/Makefile.am: * gui/simple-greeter/cutnpaste/*: Rename directory. * gui/simple-greeter/gdm-greeter-background.c: diff --git a/gui/simple-greeter/Makefile.am b/gui/simple-greeter/Makefile.am index 0881d963..045e76f1 100644 --- a/gui/simple-greeter/Makefile.am +++ b/gui/simple-greeter/Makefile.am @@ -2,12 +2,14 @@ NULL = SUBDIRS = \ libnotificationarea \ + libbackground \ $(NULL) INCLUDES = \ -I$(top_srcdir)/common \ -I$(top_srcdir)/libgreeter \ -I$(top_srcdir)/gui/simple-greeter/libnotificationarea \ + -I$(top_srcdir)/gui/simple-greeter/libbackground \ -DAUTHDIR=\""$(authdir)"\" \ -DDATADIR=\""$(datadir)"\" \ -DGDMCONFDIR=\"$(gdmconfdir)\" \ @@ -57,6 +59,7 @@ gdm_simple_greeter_LDADD = \ -L$(top_builddir)/libgreeter \ -lgreeter \ $(top_builddir)/gui/simple-greeter/libnotificationarea/libnotificationarea.la \ + $(top_builddir)/gui/simple-greeter/libbackground/libbackground.la \ $(GLIB_LIBS) \ $(DBUS_LIBS) \ $(GOBJECT_LIBS) \ diff --git a/gui/simple-greeter/libbackground/ChangeLog b/gui/simple-greeter/libbackground/ChangeLog new file mode 100644 index 00000000..c958a042 --- /dev/null +++ b/gui/simple-greeter/libbackground/ChangeLog @@ -0,0 +1,517 @@ +2007-04-16 Jens Granseuer <jensgr@gmx.net> + + Patch by: Erich Schubert <erich@debian.org> + + * applier.c: (get_geometry): fix scaling for WPTYPE_ZOOM. Fixes + bug #342356. + +2007-01-08 Rodney Dawes <dobey@novell.com> + + * preferences.c (bg_preferences_merge_entry): + Set prefs->enabled not prefs->wallpaper_enabled + Patch from Jean-Christophe Jaskula + + Fixes #339404 + +2006-08-23 Kjartan Maraas <kmaraas@gnome.org> + + * preferences.c: (bg_preferences_load), + (bg_preferences_merge_entry), (read_wptype_from_string), + (read_orientation_from_string): Make read_orientation_from_string() + and read_wptype_from_string() behave like read_color_from_string() + and adjust all callers. Avoids some excess strduping too I guess. + Closes bug #352252. + +2006-08-21 Rodney Dawes <dobey@novell.com> + + * preferences.c (bg_preferences_load): Revert previous leak fix from + Kjartan Maraas as it seems to cause crashes in nautilus + + see bug #352279 + +2006-08-21 Kjartan Maraas <kmaraas@gnome.org> + + * preferences.c: (bg_preferences_load): Don't leak gconf strings. + +2006-06-27 Sergey Udaltsov <svu@gnome.org> + + * Makefile.am: redundant GNOMELOCALEDIR removed. Patch from #345178 + applied. + +2006-01-14 Alan Swanson <swanson@ukfsn.org> + + * applier.c (get_geometry): Handle the new WPTYPE_ZOOM setting and + return proper geometry for it + + * preferences.c (_bg_wptype_values[]): Add the alias for the zoom type + (read_wptype_from_string): Handle setting the type for zoom + (bg_preferences_get_wptype_as_string): Return the string for the new + zoom setting type + + * preferences.h (_wallpaper_type_t): Add the new zoom type + + Partial code for #105231 + +2005-11-07 Alexis Robert <alexis@linuxcode.eu.org> + + Fixes #320647 + + * libbackground/preferences.c (bg_preferences_load): only use strings + returned from GConf when not NULL. + +2005-10-01 Rodney Dawes <dobey@novell.com> + + * preferences.c (bg_preferences_load, bg_preferences_merge_entry): + Make sure that the UTF8 filename is valid and exists before trying + to use it, otherwise fall back to using the filename encoding specified + by the user with the environment variables used by glib to determine + the locale encoding of filenames + + Fixes #168604 + +2005-06-10 Kjartan Maraas <kmaraas@gnome.org> + + * applier.c: (render_wallpaper), (is_nautilus_running): GCC4 + build issues. + +2005-05-08 Richard Hoelscher <rah@rahga.com> + + * applier.c (refresh_render): Remove egg_pixbuf_new_from_file_at_size, + using the gtk+-2.6 function for this instead. + + Fixes #169757 + +2005-02-10 Rodney Dawes <dobey@novell.com> + + * Makefile.am: Don't define GNOME_ICONDIR as libbackground does not + use it in any of the code + +2004-10-14 Jody Goldberg <jody@gnome.org> + + * Release 2.8.1 + +2004-06-27 Rodney Dawes <dobey@novell.com> + + * applier.c: Remove all references to #ifdef HAVE_GTK_MULTIHEAD + Patch from Kjartan Maraas <kmaraas@gnome.org> + + Fixes #142749 + +2004-04-15 Jody Goldberg <jody@gnome.org> + + * Release 2.6.1 + +2004-03-12 Chris Lahey <clahey@rigger.boston.ximian.com> + + * applier.c (refresh_render): Move the image reload into a separate function. + (size_changed_cb): Handle screen resolution changes. + +2004-03-11 Chris Lahey <clahey@rigger.boston.ximian.com> + + * applier.c (bg_applier_apply_prefs): If the image is going to be + scaled or stretched, load it at the size it's going to be + displayed. + (need_wallpaper_load_p): If the wallpaper type changed, unless it + changed between TILED and CENTERED, we need to reload the image. + +2004-04-01 Jody Goldberg <jody@gnome.org> + + * Release 2.6.0.3 + +2004-03-30 Jody Goldberg <jody@gnome.org> + + * Release 2.6.0.1 + +2004-03-23 Jody Goldberg <jody@gnome.org> + + * Release 2.6.0 + +2004-03-11 Jody Goldberg <jody@gnome.org> + + * Release 2.5.4 + +2003-12-07 Jan Arne Petersen <jpetersen@uni-bonn.de> + + * Makefile.am: remove ununsed preview-file-selection.[ch] from + build. + +2004-02-13 Jody Goldberg <jody@gnome.org> + + * Release 2.5.3 + +2004-01-14 Jody Goldberg <jody@gnome.org> + + * Release 2.5.2 + +2003-12-30 Jody Goldberg <jody@gnome.org> + + * Release 2.5.1.1 + +2003-12-30 Jody Goldberg <jody@gnome.org> + + * Release 2.5.1 + +2003-10-28 Jody Goldberg <jody@gnome.org> + + * Release 2.5.0 + +2003-07-07 Jody Goldberg <jody@gnome.org> + + * Release 2.3.4 + +2003-06-24 Jody Goldberg <jody@gnome.org> + + * Release 2.3.3 + +Mon Jun 2 13:35:49 2003 Jonathan Blandford <jrb@redhat.com> + + * preview-file-selection.c + (preview_file_selection_intelligent_scale): scaling fix. Patch + from Marcus Matèrn <marcus.matern@safecareab.com>, #113816 + +2003-05-07 Jody Goldberg <jody@gnome.org> + + * Release 2.3.1 + +2003-04-07 Pasupathi Duraisamy <pasupathi.duraisamy@wipro.com> + + * applier.c (set_root_pixmap): Fixes bogus GC creation. + patch from Anders Carlsson <andersca@gnu.org> + +2003-02-16 Kjartan Maraas <kmaraas@gnome.org> + + * applier.c: Fix a typo in a comment. + +Tue Feb 4 17:09:18 2003 Jonathan Blandford <jrb@redhat.com> + + * Release 2.2.0.1 + +Tue Jan 21 01:15:14 2003 Jonathan Blandford <jrb@gnome.org> + + * Release 2.2.0 + +Thu Jan 16 02:41:09 2003 Jonathan Blandford <jrb@gnome.org> + + * Release 2.1.7 + +2003-01-10 Jody Goldberg <jody@gnome.org> + + * Release 2.1.6 + +2002-12-18 Jody Goldberg <jody@gnome.org> + + * Release 2.1.5 + +2002-11-23 Jody Goldberg <jody@gnome.org> + + * Release 2.1.3 + +2002-11-02 Jody Goldberg <jody@gnome.org> + + * Release 2.1.2 + +2002-10-21 Jody Goldberg <jody@gnome.org> + + * Release 2.1.1 + +2002-09-13 Iain <iain@prettypeople.org> + + * preview-file-selection.c (preview_file_selection_update): Update the + label with the size of the image. + (preview_file_selection_add_preview): Add a label below the preview. + +2002-10-01 Jody Goldberg <jody@gnome.org> + + * Release 2.1.0.1 + +2002-08-21 Jody Goldberg <jody@gnome.org> + + * Release 2.1.0 + +2002-07-29 jacob berkman <jacob@ximian.com> + + * applier.c (set_root_pixmap): + (make_root_pixmap): fixes for building with gdk 2.0 + +2002-07-27 Mark McLoughlin <mark@skynet.ie> + + Add support for rendering the wallpaper on + a particular physical screen. + + * applier.[ch]: + (bg_applier_init): init screen and root_window. + (bg_applier_class_init), (bg_applier_set_prop), + (bg_applier_get_prop): add "screen" property. + (bg_applier_new_for_screen): implement. + (render_wallpaper), (render_to_screen), + (create_pixmap), (wallpaper_full_cover_p): use the + screen and root window information. + (make_root_pixmap): add a GdkScreen arg, actually + use the display we opened, use the correct root + window and not the default one + (set_root_pixmap): add a GdkScreen arg, use the + default display, use the correct root window. + +2002-06-18 Jody Goldberg <jody@gnome.org> + + http://bugzilla.gnome.org/show_bug.cgi?id=85224 + * applier.c (render_wallpaper) : clamp to avoid underflow + +2002-06-17 Jody Goldberg <jody@gnome.org> + + * Release 2.0.0 + +2002-05-31 Damon Chaplin <damon@ximian.com> + + * applier.c (bg_applier_apply_prefs): don't call set_root_pixmap() at + all if nautilus is running. It didn't do anything in this case anyway. + Removed the nice(20). A library function shouldn't do this. If + gnome-settings-daemon wants to be niced then it should do it in main() + or something like that. + (set_root_pixmap): do a final check to see if nautilus is running + before setting the pixmap. + + Fixes part of #74311. + +2002-05-21 jacob berkman <jacob@ximian.com> + + * applier.c (render_to_screen): use a gc for the pixmap not the + root window + (bg_applier_get_preview_widget): don't create the pixmap until we + are realized + (make_root_pixmap): use gdk_get_display(), not getenv ("DISPLAY"), + and set the colormap for our GdkPixmap so we can draw on it + (preview_realized_cb): create the pixmap here, and set it on our + GtkImage + + fixes #73496 + +2002-05-16 jacob berkman <jacob@ximian.com> + + * applier.c (bg_applier_apply_prefs): don't spew a warning when + files can't be loaded (helps fix #76993) + +2002-04-19 Jody Goldberg <jody@gnome.org> + + http://bugzilla.gnome.org/show_bug.cgi?id=79149 + * preferences.c (bg_preferences_clone) : fix leaks and use + gdk_color_free because some wiseguy thought GdkColours should use + memchunks. + (bg_preferences_load) : ditto. + (bg_preferences_merge_entry) : ditto. + (read_color_from_string) : ditto. + (bg_preferences_finalize) : ditto. clean out pointers to protect + against multiple calls. + +2002-04-17 Rachel Hestilow <hestilow@ximian.com> + + * applier.c (need_root_pixmap_p): Return TRUE if pixmap is NULL. + (create_pixmap): Only set pixmap if not already set. + +2002-04-17 Anders Carlsson <andersca@gnu.org> + + * preferences.c: (bg_preferences_finalize), (bg_preferences_load): + Plug leaks. Sigh. + +2002-04-07 Rachel Hestilow <hestilow@ximian.com> + + * applier.c (bg_applier_get_preview_widget): Connect to "realize" + on preview. + (preview_realized_cb): Added function to initialize preview pixmap. + +2002-03-28 Richard Hestilow <hestilow@ximian.com> + + * applier.c (bg_applier_set_prop): Only set size for preview modes. + +2002-03-28 Richard Hestilow <hestilow@ximian.com> + + * applier.c (MONITOR_CONTENTS_WIDTH, MONITOR_CONTENTS_HEIGHT): + Rename to _DEFAULT_WIDTH, _DEFAULT_HEIGHT. + (draw_disabled_message): Accept width and height as variables. + (bg_applier_class_init): Install props preview_width, preview_height. + (bg_applier_set_prop): Accept new size properties, only set to + default width/height on mode PREVIEW if uninitialized. + (bg_applier_new_at_size): Added. + (bg_applier_apply_prefs): Call draw_disabled_message with actual + width/height. + (bg_applier_get_preview_width): Create pixmap based on set size. + +2002-03-26 Dave Camp <dave@ximian.com> + + * applier.c: (bg_applier_init): Don't initialize + is_nautilus_running here (check it each time in appy_prefs). + (bg_applier_apply_prefs): Don't try to apply the background if + nautilus is running. + +2002-03-19 Richard Hestilow <hestilow@ximian.com> + + * preferences.h (wallpaper_type_t): Remove EMBOSSED since we + don't support it. + + * preferences.c: + (_bg_wptype_values, _bg_orientation_values): Move name values + to nick, change name to "correct" form. + (read_wptype_from_string, bg_preferences_get_wptype_as_string): + Remove EMBOSSSED option. + + * preview-file-selection.[ch]: Add function + preview_file_selection_intelligent_scale. + + * applier.c: Change MONITOR_CONTENTS_WIDTH/HEIGHT to 64/48 + (correct monitor ratio). + (bg_applier_apply_prefs): Disable wallpaper if WPTYPE_NONE. + (bg_applier_get_preview_widget): Create to WIDTH/HEIGHT. + (get_geometry): Remove reference to EMBOSSED. + +2002-03-17 Darin Adler <darin@bentspoon.com> + + * preferences.c: (bg_preferences_merge_entry): + Use G_GNUC_FUNCTION so we're not gcc-specific. + +2002-03-15 Seth Nickell <snickell@stanford.edu> + + * preferences.c: (bg_preferences_load), + (bg_preferences_merge_entry), (read_wptype_from_string), + (read_color_from_string), (bg_preferences_get_wptype_as_string): + * preferences.h: + + Add an enum type for specifying that we don't know the type (i.e. the + key was not available, or set to something invalid). Currently it + was using -1, which barfs with some compilers that set enums + to be uint. + +2002-03-09 Richard Hestilow <hestilow@ximian.com> + + * preview-file-selection.[ch]: Added. + + * Makefile.am: Compile preview-file-selection.c. + + * preferences.c (bg_preferences_init): Initialize adjust_opacity + to FALSE. + +2002-03-03 Alexander Larsson <alla@lysator.liu.se> + + * preferences.c (bg_preferences_save): + Save wallpaper-enabled too. + +2002-02-22 Richard Hestilow <hestilow@ximian.com> + + * preferences.[ch]: Add function bg_preferences_save. + +2002-02-17 Bradford Hovinen <hovinen@ximian.com> + + * applier.c (need_root_pixmap_p): We don't need a root pixmap if + neither a wallpaper nor a gradient is enabled + (render_to_screen): Use set_back_pixmap/set_background when just + setting a color with a root applier + (need_root_pixmap_p): If the last preferences structure had + neither gradient nor wallpaper enabled, we need a new root pixmap + (need_wallpaper_load_p): We need to reload the wallpaper pixbuf if + it is enabled and not loaded + (cleanup_cb): Free bg_applier->p->pixbuf too + (bg_applier_apply_prefs): Only add the timeout for cleanup if we + are in a root renderer; we don't need it for preview + +2002-02-12 Lauris Kaplinski <lauris@ximian.com> + + * applier.c (draw_disabled_message): Use g_object_unref for GdkGC + (render_wallpaper): Use gdk_drawable_get_size + (render_to_screen): Use gdk_get_default_root_window + (wallpaper_full_cover_p): Ditto + + * preferences.c (read_color_from_string): Use gdk_rgb_find_color + + * applier.c (bg_applier_get_preview_widget): Use gnome_program_locate_file, + replace GDK_ROOT_PARENT with gdk_get_default_root_window, deprecated + gdk_window_* methods with gdk_drawable_* ones + (bg_applier_get_preview_widget): Removed gtk_widget_push_visual, + gtk_widget_pop_visual, use gtk_image instead of gtk_pixmap + +2002-02-07 Richard Hestilow <hestilow@ximian.com> + + * applier.c (BGApplierPrivate): Add "timeout" field. + (bg_apply_cleanup_cb): Added. + (bg_applier_apply_prefs): Add/reset timeout for cleanup function + if we load a pixbuf. + +2002-02-04 Lauris Kaplinski <lauris@ximian.com> + + * preferences.c (read_wptype_from_string): Do not crash on NULL + (read_orientation_from_string): Ditto + + * applier.c (bg_applier_dispose): Replace deprecated methods + (draw_disabled_message): Use gtk_image instead of gtk_pixmap, + replace deprecated methods + (render_wallpaper): Replace deprecated methods + +2002-01-13 Seth Nickell <snickell@stanford.edu> + + reviewed by: <delete if not using a buddy> + + * Makefile.am: + * applier.c: (bg_applier_apply_prefs), + (bg_applier_get_preview_widget), (draw_disabled_message), + (create_pixmap), (get_geometry): + * preferences.c: (bg_preferences_load), + (bg_preferences_merge_entry), (read_wptype_from_string), + (read_orientation_from_string): + * preferences.h: + +2002-01-28 Richard Hestilow <hestilow@ximian.com> + + * Makefile.am: Use libtool to create the static library, thus + allowing shlibs to link to libbackground (needed for metatheme). + +2002-01-10 Bradford Hovinen <hovinen@ximian.com> + + Courtesy of Jean Schurger <jschurger@schurger.org>: + * preferences.c (bg_preferences_merge_entry): Make sure the + wallpaper filename is non-NULL before doing anything with it + +2001-12-20 Bradford Hovinen <hovinen@ximian.com> + + * applier.c (bg_applier_apply_prefs): Disable the wallpaper if we + couldn't load it + (bg_applier_apply_prefs): Create a clone of the preferences + structure first and work off of that + (wallpaper_full_cover_p): Return FALSE if the wallpaper pixbuf is NULL + + * preferences.c (bg_preferences_merge_entry): Don't actually set + the wallpaper to "enabled" unless we can load the thing + + * applier.c: Eliminate compiler warnings + + * applier.[ch]: Rename applier to bg_applier to avoid possible + namespace collision + + * preferences.[ch]: Rename preferences to bg_preferences to avoid + possible namespace collision + +2001-12-18 Bradford Hovinen <hovinen@ximian.com> + + * preferences.c: Update GConf keys to use /desktop/gnome/background + (preferences_load): Use gconf_client rather than gconf_engine + +2001-12-17 Bradford Hovinen <hovinen@ximian.com> + + * applier.c (set_root_pixmap): Set the pixmap_id correctly if + pixmap is NULL or -1. + + * preferences.c (preferences_merge_entry): Eliminate name; use + entry->key on the warning + (preferences_merge_entry): Use correct keys + + * applier.c (applier_get_preview_widget): Make sure the pixmap is + masked correctly + (applier_apply_prefs): s/gtk_object_destroy/g_object_unref/ + +2001-12-07 Bradford Hovinen <hovinen@ximian.com> + + * preferences.c (read_color_from_string): Check if string is + non-NULL + (preferences_load): Initialize the error structure + + * applier.c (applier_class_init): Initialize object_class properly + before using it; install property after {get|set}_property are set + (applier_get_preview_widget): Construct the GC before using it + diff --git a/gui/simple-greeter/libbackground/Makefile.am b/gui/simple-greeter/libbackground/Makefile.am new file mode 100644 index 00000000..0486b2be --- /dev/null +++ b/gui/simple-greeter/libbackground/Makefile.am @@ -0,0 +1,13 @@ +EXTRA_DIST = ChangeLog + +INCLUDES = \ + -DG_LOG_DOMAIN=\"capplet-common\" \ + -DGNOMELOCALEDIR="\"$(datadir)/locale\"" \ + -I$(top_srcdir)/ \ + @CAPPLET_CFLAGS@ + +noinst_LTLIBRARIES = libbackground.la + +libbackground_la_SOURCES = \ + applier.c applier.h \ + preferences.c preferences.h diff --git a/gui/simple-greeter/libbackground/applier.c b/gui/simple-greeter/libbackground/applier.c new file mode 100644 index 00000000..dcac027c --- /dev/null +++ b/gui/simple-greeter/libbackground/applier.c @@ -0,0 +1,1699 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* -*- mode: c; style: linux -*- */ + +/* applier.c + * Copyright (C) 2001 Ximian, Inc. + * + * Written by Bradford Hovinen <hovinen@ximian.com> + * + * 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, 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 <string.h> +#include <gnome.h> +#include <gdk/gdk.h> +#include <gdk/gdkx.h> +#include <gdk/gdkprivate.h> + +#include <X11/Xlib.h> +#include <X11/Xatom.h> +#include <unistd.h> + +#include "applier.h" + +#define MONITOR_CONTENTS_X 0 +#define MONITOR_CONTENTS_Y 0 +#define MONITOR_CONTENTS_DEFAULT_WIDTH 64 +#define MONITOR_CONTENTS_DEFAULT_HEIGHT 48 + +enum { + PROP_0, + PROP_TYPE, + PROP_PREVIEW_WIDTH, + PROP_PREVIEW_HEIGHT, + PROP_SCREEN +}; + +struct _BGApplierPrivate +{ + GtkWidget *preview_widget; /* The widget for previewing + * -- this is not used for + * actual rendering; it is + * returned if requested */ + BGPreferences *last_prefs; /* A cache of the last + * bg_preferences structure to + * be applied */ + + GdkPixbuf *wallpaper_pixbuf; /* The "raw" wallpaper pixbuf */ + + BGApplierType type; /* Whether we render to the + * root or the preview */ + + /* Where on the pixmap we should render the background image. Should + * have origin 0,0 and width and height equal to the desktop size if we + * are rendering to the desktop. The area to which we render the pixbuf + * will be smaller if we are rendering a centered image smaller than the + * screen or scaling and keeping aspect ratio and the background color + * is solid. */ + GdkRectangle render_geom; + + /* Where to render the pixbuf, relative to the pixmap. This will be the + * same as render_geom above if we have no solid color area to worry + * about. By convention, a negative value means that the pixbuf is + * larger than the pixmap, so the region should be fetched from a subset + * of the pixbuf. */ + GdkRectangle pixbuf_render_geom; + + /* Where to fetch the data from the pixbuf. We use this in case we are + * rendering a centered image that is larger than the size of the + * desktop. Otherwise it is (0,0) */ + GdkPoint pixbuf_xlate; + + /* Geometry of the pixbuf used to render the gradient. If the wallpaper + * is not enabled, we use the following optimization: On one dimension, + * this should be equal to the dimension of render_geom, while on the + * other dimension it should be the constant 32. This avoids wasting + * memory with rendundant data. */ + GdkPoint grad_geom; + + GdkPixbuf *pixbuf; /* "working" pixbuf - All data + * are rendered onto this for + * display */ + GdkPixmap *pixmap; /* Pixmap onto which we dump the + * pixbuf above when we are ready + * to render to the screen */ + gboolean pixmap_is_set; /* TRUE iff the pixmap above + * has been set as the root + * pixmap */ + guint timeout; /* "Cleanup" timeout handler; + * reset to 30 seconds every + * time apply is called. */ + GdkWindow *root_window; /* Root window on which to + * render the background */ + GdkScreen *screen; /* Screen on which to render + * the background */ + guint size_changed_cb_id; /* Signal connection id. */ +}; + +static GObjectClass *parent_class; + +static void bg_applier_init (BGApplier *prefs, + BGApplierClass *class); +static void bg_applier_class_init (BGApplierClass *class); +static void bg_applier_base_init (BGApplierClass *class); + +static void bg_applier_set_prop (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void bg_applier_get_prop (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); + +static void bg_applier_dispose (GObject *object); +static void bg_applier_finalize (GObject *object); + +static void run_render_pipeline (BGApplier *bg_applier, + const BGPreferences *prefs); +static void draw_disabled_message (GtkWidget *widget, + const guint width, + const guint height); + +static void size_changed_cb (GdkScreen *screen, + BGApplier *bg_applier); +static void render_background (BGApplier *bg_applier, + const BGPreferences *prefs); +static void render_wallpaper (BGApplier *bg_applier, + const BGPreferences *prefs); +static void render_to_screen (BGApplier *bg_applier, + const BGPreferences *prefs); +static void create_pixmap (BGApplier *bg_applier, + const BGPreferences *prefs); +static void get_geometry (wallpaper_type_t wallpaper_type, + GdkPixbuf *pixbuf, + GdkRectangle *field_geom, + GdkRectangle *virtual_geom, + GdkRectangle *dest_geom, + GdkRectangle *src_geom); + +static GdkPixbuf *place_pixbuf (GdkPixbuf *dest_pixbuf, + GdkPixbuf *src_pixbuf, + GdkRectangle *dest_geom, + GdkRectangle *src_geom, + guint alpha, + GdkColor *bg_color); +static GdkPixbuf *tile_pixbuf (GdkPixbuf *dest_pixbuf, + GdkPixbuf *src_pixbuf, + GdkRectangle *field_geom, + guint alpha, + GdkColor *bg_color); +static void fill_gradient (GdkPixbuf *pixbuf, + GdkColor *c1, + GdkColor *c2, + orientation_t orientation); + +static gboolean need_wallpaper_load_p (const BGApplier *bg_applier, + const BGPreferences *prefs); +static gboolean need_root_pixmap_p (const BGApplier *bg_applier, + const BGPreferences *prefs); +static gboolean wallpaper_full_cover_p (const BGApplier *bg_applier, + const BGPreferences *prefs); +static gboolean render_small_pixmap_p (const BGPreferences *prefs); + +static GdkPixmap *make_root_pixmap (GdkScreen *screen, + gint width, + gint height); +static void set_root_pixmap (GdkPixmap *pixmap, + GdkScreen *screen); + +static gboolean is_nautilus_running (void); + +static gboolean cleanup_cb (BGApplier *bg_applier); + +static void preview_realized_cb (GtkWidget *preview, + BGApplier *bg_applier); + +GType +bg_applier_get_type (void) +{ + static GType bg_applier_type = 0; + + if (!bg_applier_type) { + static GTypeInfo bg_applier_info = { + sizeof (BGApplierClass), + (GBaseInitFunc) bg_applier_base_init, + NULL, /* GBaseFinalizeFunc */ + (GClassInitFunc) bg_applier_class_init, + NULL, /* GClassFinalizeFunc */ + NULL, /* user-supplied data */ + sizeof (BGApplier), + 0, /* n_preallocs */ + (GInstanceInitFunc) bg_applier_init, + NULL + }; + + bg_applier_type = + g_type_register_static (G_TYPE_OBJECT, + "BGApplier", + &bg_applier_info, 0); + } + + return bg_applier_type; +} + +static void +bg_applier_init (BGApplier *bg_applier, BGApplierClass *class) +{ + bg_applier->p = g_new0 (BGApplierPrivate, 1); + bg_applier->p->last_prefs = NULL; + bg_applier->p->pixbuf = NULL; + bg_applier->p->wallpaper_pixbuf = NULL; + bg_applier->p->timeout = 0; + bg_applier->p->render_geom.width = -1; + bg_applier->p->render_geom.height = -1; + bg_applier->p->type = BG_APPLIER_PREVIEW; + + bg_applier->p->screen = gdk_screen_get_default (); + bg_applier->p->root_window = gdk_screen_get_root_window (bg_applier->p->screen); + + bg_applier->p->size_changed_cb_id = 0; +} + +static void +bg_applier_class_init (BGApplierClass *class) +{ + GObjectClass *object_class; + + object_class = G_OBJECT_CLASS (class); + + object_class->dispose = bg_applier_dispose; + object_class->finalize = bg_applier_finalize; + object_class->set_property = bg_applier_set_prop; + object_class->get_property = bg_applier_get_prop; + + g_object_class_install_property + (object_class, PROP_TYPE, + g_param_spec_int ("type", + _("Type"), + _("Type of bg_applier: BG_APPLIER_ROOT for root window or BG_APPLIER_PREVIEW for preview"), + 0, 1, 0, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property + (object_class, PROP_PREVIEW_WIDTH, + g_param_spec_uint ("preview_width", + _("Preview Width"), + _("Width if applier is a preview: Defaults to 64."), + 1, 65535, MONITOR_CONTENTS_DEFAULT_WIDTH, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property + (object_class, PROP_PREVIEW_HEIGHT, + g_param_spec_uint ("preview_height", + _("Preview Height"), + _("Height if applier is a preview: Defaults to 48."), + 1, 65535, MONITOR_CONTENTS_DEFAULT_HEIGHT, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property + (object_class, PROP_SCREEN, + g_param_spec_object ("screen", + _("Screen"), + _("Screen on which BGApplier is to draw"), + GDK_TYPE_SCREEN, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + parent_class = + G_OBJECT_CLASS (g_type_class_ref (G_TYPE_OBJECT)); +} + +static void +bg_applier_base_init (BGApplierClass *class) +{ +} + +static void +bg_applier_set_prop (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + BGApplier *bg_applier; + + g_return_if_fail (object != NULL); + g_return_if_fail (IS_BG_APPLIER (object)); + + bg_applier = BG_APPLIER (object); + + switch (prop_id) { + case PROP_TYPE: + bg_applier->p->type = g_value_get_int (value); + + switch (bg_applier->p->type) { + case BG_APPLIER_ROOT: + bg_applier->p->render_geom.x = 0; + bg_applier->p->render_geom.y = 0; + bg_applier->p->render_geom.width = gdk_screen_get_width (bg_applier->p->screen); + bg_applier->p->render_geom.height = gdk_screen_get_height (bg_applier->p->screen); + bg_applier->p->pixmap = NULL; + bg_applier->p->pixmap_is_set = FALSE; + + if (bg_applier->p->size_changed_cb_id == 0) + bg_applier->p->size_changed_cb_id = g_signal_connect (bg_applier->p->screen, "size_changed", + G_CALLBACK (size_changed_cb), bg_applier); + break; + + case BG_APPLIER_PREVIEW: + if (bg_applier->p->size_changed_cb_id) + g_signal_handler_disconnect (bg_applier->p->screen, + bg_applier->p->size_changed_cb_id); + bg_applier->p->size_changed_cb_id = 0; + bg_applier->p->render_geom.x = MONITOR_CONTENTS_X; + bg_applier->p->render_geom.y = MONITOR_CONTENTS_Y; + + if (bg_applier->p->render_geom.width == -1) + { + bg_applier->p->render_geom.width = MONITOR_CONTENTS_DEFAULT_WIDTH; + bg_applier->p->render_geom.height = MONITOR_CONTENTS_DEFAULT_HEIGHT; + } + + break; + + default: + g_critical ("Bad bg_applier type: %d", bg_applier->p->type); + break; + } + + break; + + case PROP_PREVIEW_WIDTH: + if (bg_applier->p->type == BG_APPLIER_PREVIEW) + bg_applier->p->render_geom.width = g_value_get_uint (value); + break; + + case PROP_PREVIEW_HEIGHT: + if (bg_applier->p->type == BG_APPLIER_PREVIEW) + bg_applier->p->render_geom.height = g_value_get_uint (value); + break; + + case PROP_SCREEN: + if (bg_applier->p->type == BG_APPLIER_ROOT) { + if (bg_applier->p->size_changed_cb_id) + g_signal_handler_disconnect (bg_applier->p->screen, + bg_applier->p->size_changed_cb_id); + bg_applier->p->screen = g_value_get_object (value); + bg_applier->p->root_window = gdk_screen_get_root_window (bg_applier->p->screen); + bg_applier->p->render_geom.width = gdk_screen_get_width (bg_applier->p->screen); + bg_applier->p->render_geom.height = gdk_screen_get_height (bg_applier->p->screen); + bg_applier->p->size_changed_cb_id = g_signal_connect (bg_applier->p->screen, "size_changed", + G_CALLBACK (size_changed_cb), bg_applier); + } + break; + + default: + g_warning ("Bad property set"); + break; + } +} + +static void +bg_applier_get_prop (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + BGApplier *bg_applier; + + g_return_if_fail (object != NULL); + g_return_if_fail (IS_BG_APPLIER (object)); + + bg_applier = BG_APPLIER (object); + + switch (prop_id) { + case PROP_TYPE: + g_value_set_int (value, bg_applier->p->type); + break; + + case PROP_SCREEN: + g_value_set_object (value, bg_applier->p->screen); + break; + + default: + g_warning ("Bad property get"); + break; + } +} + +static void +bg_applier_dispose (GObject *object) +{ + BGApplier *bg_applier; + + g_return_if_fail (object != NULL); + g_return_if_fail (IS_BG_APPLIER (object)); + + bg_applier = BG_APPLIER (object); + + g_assert (bg_applier->p->pixbuf == NULL); + + if (bg_applier->p->last_prefs != NULL) + g_object_unref (G_OBJECT (bg_applier->p->last_prefs)); + bg_applier->p->last_prefs = NULL; + + if (bg_applier->p->wallpaper_pixbuf != NULL) + g_object_unref (G_OBJECT (bg_applier->p->wallpaper_pixbuf)); + bg_applier->p->wallpaper_pixbuf = NULL; + + if (bg_applier->p->size_changed_cb_id) + g_signal_handler_disconnect (bg_applier->p->screen, + bg_applier->p->size_changed_cb_id); + bg_applier->p->size_changed_cb_id = 0; + + parent_class->dispose (object); +} + +static void +bg_applier_finalize (GObject *object) +{ + BGApplier *bg_applier; + + g_return_if_fail (object != NULL); + g_return_if_fail (IS_BG_APPLIER (object)); + + bg_applier = BG_APPLIER (object); + + g_free (bg_applier->p); + + parent_class->finalize (object); +} + +GObject * +bg_applier_new (BGApplierType type) +{ + GObject *object; + + object = g_object_new (bg_applier_get_type (), + "type", type, + NULL); + + return object; +} + +GObject * +bg_applier_new_at_size (BGApplierType type, + const guint width, + const guint height) +{ + GObject *object; + + object = g_object_new (bg_applier_get_type (), + "type", type, + "preview_width", width, + "preview_height", height, + NULL); + + return object; +} + +GObject * +bg_applier_new_for_screen (BGApplierType type, + GdkScreen *screen) +{ + GObject *object; + + g_return_val_if_fail (type == BG_APPLIER_ROOT, NULL); + + object = g_object_new (bg_applier_get_type (), + "type", type, + "screen", screen, + NULL); + return object; +} + +static void +refresh_render (BGApplier *bg_applier, + BGPreferences *prefs, + gboolean need_wallpaper_load) +{ + if (bg_applier->p->type == BG_APPLIER_ROOT && is_nautilus_running ()) { + return; + } + + if (!prefs->enabled) { + if (bg_applier->p->type == BG_APPLIER_PREVIEW) + draw_disabled_message (bg_applier_get_preview_widget (bg_applier), bg_applier->p->render_geom.width, bg_applier->p->render_geom.height); + return; + } + + if (need_wallpaper_load) { + if (bg_applier->p->wallpaper_pixbuf != NULL) + g_object_unref (G_OBJECT (bg_applier->p->wallpaper_pixbuf)); + + bg_applier->p->wallpaper_pixbuf = NULL; + + if (prefs->wallpaper_enabled) { + g_return_if_fail (prefs->wallpaper_filename != NULL); + + if (prefs->wallpaper_type == WPTYPE_STRETCHED || + prefs->wallpaper_type == WPTYPE_SCALED) { + bg_applier->p->wallpaper_pixbuf = + gdk_pixbuf_new_from_file_at_scale (prefs->wallpaper_filename, + bg_applier->p->render_geom.width, + bg_applier->p->render_geom.height, + prefs->wallpaper_type == WPTYPE_SCALED, + NULL); + } else { + bg_applier->p->wallpaper_pixbuf = + gdk_pixbuf_new_from_file (prefs->wallpaper_filename, NULL); + } + + if (bg_applier->p->wallpaper_pixbuf == NULL) { + prefs->wallpaper_enabled = FALSE; + } + else if (bg_applier->p->type == BG_APPLIER_ROOT) { + if (bg_applier->p->timeout) + g_source_remove (bg_applier->p->timeout); + bg_applier->p->timeout = g_timeout_add (30000, (GSourceFunc) cleanup_cb, bg_applier); + } + } + } + + run_render_pipeline (bg_applier, prefs); + + if (bg_applier->p->type == BG_APPLIER_PREVIEW && bg_applier->p->preview_widget != NULL) + gtk_widget_queue_draw (bg_applier->p->preview_widget); +} + +static void +size_changed_cb (GdkScreen *screen, + BGApplier *bg_applier) +{ + bg_applier->p->render_geom.width = gdk_screen_get_width (bg_applier->p->screen); + bg_applier->p->render_geom.height = gdk_screen_get_height (bg_applier->p->screen); + if (bg_applier->p->last_prefs) { + refresh_render (bg_applier, + bg_applier->p->last_prefs, + TRUE); + } +} + +void +bg_applier_apply_prefs (BGApplier *bg_applier, + const BGPreferences *prefs) +{ + BGPreferences *new_prefs; + + g_return_if_fail (bg_applier != NULL); + g_return_if_fail (IS_BG_APPLIER (bg_applier)); + + new_prefs = BG_PREFERENCES (bg_preferences_clone (prefs)); + + if (new_prefs->wallpaper_type == WPTYPE_NONE) + { + new_prefs->wallpaper_enabled = FALSE; + new_prefs->wallpaper_type = WPTYPE_CENTERED; + } + + refresh_render (bg_applier, new_prefs, need_wallpaper_load_p (bg_applier, new_prefs)); + + if (bg_applier->p->last_prefs != NULL) + g_object_unref (G_OBJECT (bg_applier->p->last_prefs)); + + bg_applier->p->last_prefs = new_prefs; +} + +gboolean +bg_applier_render_color_p (const BGApplier *bg_applier, const BGPreferences *prefs) +{ + g_return_val_if_fail (bg_applier != NULL, FALSE); + g_return_val_if_fail (IS_BG_APPLIER (bg_applier), FALSE); + g_return_val_if_fail (prefs != NULL, FALSE); + g_return_val_if_fail (IS_BG_PREFERENCES (prefs), FALSE); + + return prefs->enabled && !wallpaper_full_cover_p (bg_applier, prefs); +} + +GtkWidget * +bg_applier_get_preview_widget (BGApplier *bg_applier) +{ + if (bg_applier->p->preview_widget == NULL) + { + bg_applier->p->preview_widget = gtk_image_new (); + + /* We need to initialize the pixmap, but this + * needs GCs, so we have to wait until realize. */ + g_signal_connect (G_OBJECT (bg_applier->p->preview_widget), + "realize", + (GCallback) preview_realized_cb, + bg_applier); + } + + return bg_applier->p->preview_widget; +} + +GdkPixbuf * +bg_applier_get_wallpaper_pixbuf (BGApplier *bg_applier) +{ + g_return_val_if_fail (bg_applier != NULL, NULL); + g_return_val_if_fail (IS_BG_APPLIER (bg_applier), NULL); + + return bg_applier->p->wallpaper_pixbuf; +} + +static void +draw_disabled_message (GtkWidget *widget, const guint w, const guint h) +{ + GdkPixmap *pixmap; + GdkColor color; + PangoLayout *layout; + PangoRectangle extents; + GdkGC *gc; + gint x, y; + const char *disabled_string = _("Disabled"); + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_IMAGE (widget)); + + x = MONITOR_CONTENTS_X; + y = MONITOR_CONTENTS_Y; + + if (!GTK_WIDGET_REALIZED (widget)) { + gtk_widget_realize (widget); + } + + gtk_image_get_pixmap (GTK_IMAGE (widget), &pixmap, NULL); + gc = gdk_gc_new (widget->window); + + color.red = 0x0; + color.green = 0x0; + color.blue = 0x0; + gdk_gc_set_rgb_fg_color (gc, &color); + gdk_draw_rectangle (pixmap, gc, TRUE, x, y, w, h); + + layout = gtk_widget_create_pango_layout (widget, disabled_string); + pango_layout_get_pixel_extents (layout, &extents, NULL); + + color.red = 0xffff; + color.green = 0xffff; + color.blue = 0xffff; + gdk_gc_set_rgb_fg_color (gc, &color); + + /* fixme: I do not understand the logic (Lauris) */ + + gdk_draw_layout (widget->window, + gc, + x + (w - extents.width) / 2, + y + (h - extents.height) / 2 + extents.height / 2, + layout); + + g_object_unref (G_OBJECT (gc)); + g_object_unref (G_OBJECT (layout)); +} + +static void +run_render_pipeline (BGApplier *bg_applier, const BGPreferences *prefs) +{ + g_return_if_fail (bg_applier != NULL); + g_return_if_fail (IS_BG_APPLIER (bg_applier)); + g_return_if_fail (prefs != NULL); + g_return_if_fail (IS_BG_PREFERENCES (prefs)); + + g_assert (bg_applier->p->pixbuf == NULL); + + /* Initialize bg_applier->p->render_geom */ + bg_applier->p->pixbuf_render_geom.x = bg_applier->p->render_geom.x; + bg_applier->p->pixbuf_render_geom.y = bg_applier->p->render_geom.y; + bg_applier->p->pixbuf_render_geom.width = bg_applier->p->render_geom.width; + bg_applier->p->pixbuf_render_geom.height = bg_applier->p->render_geom.height; + bg_applier->p->pixbuf_xlate.x = 0; + bg_applier->p->pixbuf_xlate.y = 0; + + render_background (bg_applier, prefs); + + if (need_root_pixmap_p (bg_applier, prefs)) + create_pixmap (bg_applier, prefs); + + render_wallpaper (bg_applier, prefs); + render_to_screen (bg_applier, prefs); + + if (bg_applier->p->pixbuf != NULL) { + g_object_unref (G_OBJECT (bg_applier->p->pixbuf)); + bg_applier->p->pixbuf = NULL; + } +} + +/* Create the gradient image if necessary and put it into a fresh pixbuf + * + * Preconditions: + * 1. prefs is valid + * 2. The old bg_applier->p->pixbuf, if it existed, has been destroyed + * + * Postconditions (assuming gradient is enabled): + * 1. bg_applier->p->pixbuf contains a newly rendered gradient + */ + +static void +render_background (BGApplier *bg_applier, const BGPreferences *prefs) +{ + g_return_if_fail (bg_applier != NULL); + g_return_if_fail (IS_BG_APPLIER (bg_applier)); + g_return_if_fail (prefs != NULL); + g_return_if_fail (IS_BG_PREFERENCES (prefs)); + + if (prefs->gradient_enabled && !wallpaper_full_cover_p (bg_applier, prefs)) { + bg_applier->p->grad_geom.x = bg_applier->p->render_geom.width; + bg_applier->p->grad_geom.y = bg_applier->p->render_geom.height; + + if (bg_applier->p->type == BG_APPLIER_ROOT && !prefs->wallpaper_enabled) { + if (prefs->orientation == ORIENTATION_HORIZ) + bg_applier->p->grad_geom.y = 32; + else + bg_applier->p->grad_geom.x = 32; + } + + bg_applier->p->pixbuf = + gdk_pixbuf_new (GDK_COLORSPACE_RGB, + FALSE, 8, + bg_applier->p->grad_geom.x, + bg_applier->p->grad_geom.y); + + fill_gradient (bg_applier->p->pixbuf, + prefs->color1, prefs->color2, + prefs->orientation); + + bg_applier->p->pixbuf_render_geom.width = bg_applier->p->grad_geom.x; + bg_applier->p->pixbuf_render_geom.height = bg_applier->p->grad_geom.y; + } +} + +/* Render the wallpaper onto the pixbuf-in-progress. + * + * Preconditions: + * 1. The wallpaper pixbuf has been loaded and is in + * bg_applier->p->wallpaper_pixbuf. + * 2. The structure bg_applier->p->render_geom is filled out properly as + * described in the documentation above (this should be invariant). + * 3. The various fields in prefs are valid + * + * Postconditions (assuming wallpaper is enabled): + * 1. bg_applier->p->pixbuf contains the pixbuf-in-progress with the wallpaper + * correctly rendered. + * 2. bg_applier->p->pixbuf_render_geom has been modified, if necessary, + * according to the requirements of the wallpaper; it should be set by + * default to be the same as bg_applier->p->render_geom. + */ + +static void +render_wallpaper (BGApplier *bg_applier, const BGPreferences *prefs) +{ + GdkRectangle src_geom = { 0, }; + GdkRectangle dest_geom = { 0, }; + GdkRectangle virtual_geom; + GdkPixbuf *prescaled_pixbuf = NULL; + guint alpha; + gint tmp1, tmp2; + gint pwidth, pheight; + + g_return_if_fail (bg_applier != NULL); + g_return_if_fail (IS_BG_APPLIER (bg_applier)); + g_return_if_fail (prefs != NULL); + g_return_if_fail (IS_BG_PREFERENCES (prefs)); + + if (prefs->wallpaper_enabled) { + if (bg_applier->p->wallpaper_pixbuf == NULL) + return; + + gdk_drawable_get_size (bg_applier->p->root_window, &tmp1, &tmp2); + virtual_geom.x = virtual_geom.y = 0; + virtual_geom.width = tmp1; + virtual_geom.height = tmp2; + + pwidth = gdk_pixbuf_get_width (bg_applier->p->wallpaper_pixbuf); + pheight = gdk_pixbuf_get_height (bg_applier->p->wallpaper_pixbuf); + + get_geometry (prefs->wallpaper_type, + bg_applier->p->wallpaper_pixbuf, + &(bg_applier->p->render_geom), + &virtual_geom, &dest_geom, &src_geom); + + /* Modify bg_applier->p->pixbuf_render_geom if necessary */ + if (bg_applier->p->pixbuf == NULL) { /* This means we didn't render a gradient */ + bg_applier->p->pixbuf_render_geom.x = dest_geom.x + bg_applier->p->render_geom.x; + bg_applier->p->pixbuf_render_geom.y = dest_geom.y + bg_applier->p->render_geom.y; + bg_applier->p->pixbuf_render_geom.width = dest_geom.width; + bg_applier->p->pixbuf_render_geom.height = dest_geom.height; + } + + if (prefs->wallpaper_type == WPTYPE_TILED) { + if (dest_geom.width != pwidth || dest_geom.height != pheight) { + int hscale = pwidth * bg_applier->p->render_geom.width / virtual_geom.width; + int vscale = pheight * bg_applier->p->render_geom.height / virtual_geom.height; + + if (hscale < 1) hscale = 1; + if (vscale < 1) vscale = 1; + + prescaled_pixbuf = gdk_pixbuf_scale_simple + (bg_applier->p->wallpaper_pixbuf, hscale, vscale, + GDK_INTERP_BILINEAR); + } else { + prescaled_pixbuf = bg_applier->p->wallpaper_pixbuf; + g_object_ref (G_OBJECT (prescaled_pixbuf)); + } + } + + if (prefs->adjust_opacity) { + alpha = 2.56 * prefs->opacity; + alpha = alpha * alpha / 256; + alpha = CLAMP (alpha, 0, 255); + } else { + alpha = 255; + } + + if (prefs->wallpaper_type == WPTYPE_TILED) + bg_applier->p->pixbuf = tile_pixbuf (bg_applier->p->pixbuf, + prescaled_pixbuf, + &(bg_applier->p->render_geom), + alpha, prefs->color1); + else + bg_applier->p->pixbuf = place_pixbuf (bg_applier->p->pixbuf, + bg_applier->p->wallpaper_pixbuf, + &dest_geom, &src_geom, + alpha, prefs->color1); + + if (bg_applier->p->pixbuf == bg_applier->p->wallpaper_pixbuf) { + bg_applier->p->pixbuf_xlate.x = src_geom.x; + bg_applier->p->pixbuf_xlate.y = src_geom.y; + } + + if (prescaled_pixbuf != NULL) + g_object_unref (G_OBJECT (prescaled_pixbuf)); + } +} + +/* Take whatever we have rendered and transfer it to the display. + * + * Preconditions: + * 1. We have already rendered the gradient and wallpaper, and + * bg_applier->p->pixbuf is a valid GdkPixbuf containing that rendered data. + * 2. The structure bg_applier->p->pixbuf_render_geom contains the coordonites on + * the destination visual to which we should render the contents of + * bg_applier->p->pixbuf + * 3. The structure bg_applier->p->render_geom contains the total area that the + * background should cover (i.e. the whole desktop if we are rendering to + * the root window, or the region inside the monitor if we are rendering to + * the preview). + * 4. The strucutre prefs->color1 contains the background color to be used on + * areas not covered by the above pixbuf. + */ + +static void +render_to_screen (BGApplier *bg_applier, const BGPreferences *prefs) +{ + GdkGC *gc; + + g_return_if_fail (bg_applier != NULL); + g_return_if_fail (IS_BG_APPLIER (bg_applier)); + g_return_if_fail (prefs != NULL); + g_return_if_fail (IS_BG_PREFERENCES (prefs)); + + gc = gdk_gc_new (bg_applier->p->pixmap); + + if (bg_applier->p->pixbuf != NULL) { + if (bg_applier->p->pixbuf_render_geom.x != 0 || + bg_applier->p->pixbuf_render_geom.y != 0 || + bg_applier->p->pixbuf_render_geom.width != bg_applier->p->render_geom.width || + bg_applier->p->pixbuf_render_geom.height != bg_applier->p->render_geom.height) + { + gboolean success; + +#if 0 + gdk_color_alloc (gdk_window_get_colormap (bg_applier->p->root_window), prefs->color1); +#else + gdk_colormap_alloc_colors (gdk_drawable_get_colormap (bg_applier->p->root_window), + prefs->color1, 1, FALSE, TRUE, &success); +#endif + + gdk_gc_set_foreground (gc, prefs->color1); + gdk_draw_rectangle (bg_applier->p->pixmap, gc, TRUE, + bg_applier->p->render_geom.x, + bg_applier->p->render_geom.y, + bg_applier->p->render_geom.width, + bg_applier->p->render_geom.height); + } + + gdk_pixbuf_render_to_drawable + (bg_applier->p->pixbuf, + bg_applier->p->pixmap, gc, + bg_applier->p->pixbuf_xlate.x, + bg_applier->p->pixbuf_xlate.y, + bg_applier->p->pixbuf_render_geom.x, + bg_applier->p->pixbuf_render_geom.y, + bg_applier->p->pixbuf_render_geom.width, + bg_applier->p->pixbuf_render_geom.height, + GDK_RGB_DITHER_MAX, 0, 0); + } else { + if (bg_applier->p->type == BG_APPLIER_ROOT) { + gboolean success; + +#if 0 + gdk_color_alloc (gdk_window_get_colormap (bg_applier->p->root_window), prefs->color1); +#else + gdk_colormap_alloc_colors (gdk_drawable_get_colormap (bg_applier->p->root_window), + prefs->color1, 1, FALSE, TRUE, &success); +#endif + gdk_window_set_background (bg_applier->p->root_window, prefs->color1); + gdk_window_clear (bg_applier->p->root_window); + } + else if (bg_applier->p->type == BG_APPLIER_PREVIEW) { + gboolean success; + +#if 0 + gdk_color_alloc (gdk_window_get_colormap (bg_applier->p->preview_widget->window), prefs->color1); +#else + gdk_colormap_alloc_colors (gdk_drawable_get_colormap (bg_applier->p->root_window), + prefs->color1, 1, FALSE, TRUE, &success); +#endif + + if (bg_applier->p->type == BG_APPLIER_PREVIEW) { + gdk_gc_set_foreground (gc, prefs->color1); + gdk_draw_rectangle (bg_applier->p->pixmap, gc, TRUE, + bg_applier->p->render_geom.x, + bg_applier->p->render_geom.y, + bg_applier->p->render_geom.width, + bg_applier->p->render_geom.height); + } + else if (bg_applier->p->type == BG_APPLIER_ROOT) { + gdk_window_set_back_pixmap (bg_applier->p->root_window, NULL, FALSE); + gdk_window_set_background (bg_applier->p->root_window, prefs->color1); + } + } + } + + if (bg_applier->p->type == BG_APPLIER_ROOT && !bg_applier->p->pixmap_is_set && + (prefs->wallpaper_enabled || prefs->gradient_enabled)) + set_root_pixmap (bg_applier->p->pixmap, bg_applier->p->screen); + else if (bg_applier->p->type == BG_APPLIER_ROOT && !bg_applier->p->pixmap_is_set) + set_root_pixmap (NULL, bg_applier->p->screen); + + g_object_unref (G_OBJECT (gc)); +} + +/* Create a pixmap that will replace the current root pixmap. This function has + * no effect if the bg_applier is for the preview window + */ + +static void +create_pixmap (BGApplier *bg_applier, const BGPreferences *prefs) +{ + gint width, height; + + g_return_if_fail (bg_applier != NULL); + g_return_if_fail (IS_BG_APPLIER (bg_applier)); + g_return_if_fail (prefs != NULL); + g_return_if_fail (IS_BG_PREFERENCES (prefs)); + + switch (bg_applier->p->type) { + case BG_APPLIER_ROOT: + if (prefs->gradient_enabled && !prefs->wallpaper_enabled) { + width = bg_applier->p->grad_geom.x; + height = bg_applier->p->grad_geom.y; + } else { + width = bg_applier->p->render_geom.width; + height = bg_applier->p->render_geom.height; + } + + bg_applier->p->pixmap = make_root_pixmap (bg_applier->p->screen, width, height); + bg_applier->p->pixmap_is_set = FALSE; + break; + + case BG_APPLIER_PREVIEW: + bg_applier_get_preview_widget (bg_applier); + + if (!GTK_WIDGET_REALIZED (bg_applier->p->preview_widget)) + gtk_widget_realize (bg_applier->p->preview_widget); + +#if 0 + bg_applier->p->pixmap = GTK_PIXMAP (bg_applier->p->preview_widget)->pixmap; +#else + if (!bg_applier->p->pixmap) + gtk_image_get_pixmap (GTK_IMAGE (bg_applier->p->preview_widget), &bg_applier->p->pixmap, NULL); +#endif + bg_applier->p->pixmap_is_set = TRUE; + break; + } +} + +/* Compute geometry information based on the wallpaper type. In particular, + * determine where on the destination visual the wallpaper should be rendered + * and where the data from the source pixbuf the image should be fetched. + */ + +static void +get_geometry (wallpaper_type_t wallpaper_type, + GdkPixbuf *pixbuf, + GdkRectangle *field_geom, + GdkRectangle *virtual_geom, + GdkRectangle *dest_geom, + GdkRectangle *src_geom) +{ + gdouble asp, xfactor, yfactor; + gint pwidth, pheight; + gint st = 0; + + xfactor = (gdouble) field_geom->width / (gdouble) virtual_geom->width; + yfactor = (gdouble) field_geom->height / (gdouble) virtual_geom->height; + + pwidth = gdk_pixbuf_get_width (pixbuf); + pheight = gdk_pixbuf_get_height (pixbuf); + + switch (wallpaper_type) { + case WPTYPE_TILED: + src_geom->x = src_geom->y = 0; + dest_geom->x = dest_geom->y = 0; + + src_geom->width = pwidth; + src_geom->height = pheight; + + dest_geom->width = field_geom->width; + dest_geom->height = field_geom->height; + + break; + + case WPTYPE_CENTERED: + if (virtual_geom->width < pwidth) { + src_geom->width = virtual_geom->width; + src_geom->x = (pwidth - virtual_geom->width) / 2; + dest_geom->width = field_geom->width; + dest_geom->x = 0; + } else { + src_geom->width = pwidth; + src_geom->x = 0; + dest_geom->width = MIN ((gdouble) src_geom->width * xfactor, field_geom->width); + dest_geom->x = (field_geom->width - dest_geom->width) / 2; + } + + if (virtual_geom->height < pheight) { + src_geom->height = virtual_geom->height; + src_geom->y = (pheight - virtual_geom->height) / 2; + dest_geom->height = field_geom->height; + dest_geom->y = 0; + } else { + src_geom->height = pheight; + src_geom->y = 0; + dest_geom->height = MIN ((gdouble) src_geom->height * yfactor, field_geom->height); + dest_geom->y = (field_geom->height - dest_geom->height) / 2; + } + + break; + + case WPTYPE_SCALED: + asp = (gdouble) pwidth / (gdouble) virtual_geom->width; + + if (asp < (gdouble) pheight / virtual_geom->height) { + asp = (gdouble) pheight / (gdouble) virtual_geom->height; + st = 1; + } + + if (st) { + dest_geom->width = pwidth / asp * xfactor; + dest_geom->height = field_geom->height; + dest_geom->x = (field_geom->width - dest_geom->width) / 2; + dest_geom->y = 0; + } else { + dest_geom->height = pheight / asp * yfactor; + dest_geom->width = field_geom->width; + dest_geom->x = 0; + dest_geom->y = (field_geom->height - dest_geom->height) / 2; + } + + src_geom->x = src_geom->y = 0; + src_geom->width = pwidth; + src_geom->height = pheight; + + break; + + case WPTYPE_ZOOM: + asp = (gdouble) pwidth / (gdouble) virtual_geom->width; + + if (asp > (gdouble) pheight / virtual_geom->height) { + src_geom->width = pheight * virtual_geom->width / virtual_geom->height; + src_geom->height = pheight; + src_geom->x = (pwidth - src_geom->width) / 2; + src_geom->y = 0; + } else { + src_geom->width = pwidth; + src_geom->height = pwidth * virtual_geom->height / virtual_geom->width; + src_geom->x = 0; + src_geom->y = (pheight - src_geom->height) / 2; + } + + dest_geom->x = dest_geom->y = 0; + dest_geom->width = field_geom->width; + dest_geom->height = field_geom->height; + + break; + + case WPTYPE_STRETCHED: + dest_geom->width = field_geom->width; + dest_geom->height = field_geom->height; + dest_geom->x = 0; + dest_geom->y = 0; + src_geom->x = src_geom->y = 0; + src_geom->width = pwidth; + src_geom->height = pheight; + break; + default: + g_error ("Bad wallpaper type"); + break; + } +} + +/* Place one pixbuf onto another, compositing and scaling as necessary */ + +static GdkPixbuf * +place_pixbuf (GdkPixbuf *dest_pixbuf, + GdkPixbuf *src_pixbuf, + GdkRectangle *dest_geom, + GdkRectangle *src_geom, + guint alpha, + GdkColor *bg_color) +{ + gboolean need_composite; + gboolean need_scaling; + gdouble scale_x, scale_y; + gint real_dest_x, real_dest_y; + guint colorv; + + need_composite = (alpha < 255 || gdk_pixbuf_get_has_alpha (src_pixbuf)); + need_scaling = ((dest_geom->width != src_geom->width) || (dest_geom->height != src_geom->height)); + + if (need_scaling) { + scale_x = (gdouble) dest_geom->width / (gdouble) src_geom->width; + scale_y = (gdouble) dest_geom->height / (gdouble) src_geom->height; + } else { + scale_x = scale_y = 1.0; + } + + if (need_composite && dest_pixbuf != NULL) { + gdk_pixbuf_composite + (src_pixbuf, dest_pixbuf, + dest_geom->x, dest_geom->y, + dest_geom->width, + dest_geom->height, + dest_geom->x - src_geom->x * scale_x, + dest_geom->y - src_geom->y * scale_y, + scale_x, scale_y, + GDK_INTERP_BILINEAR, + alpha); + } + else if (need_composite) { + dest_pixbuf = gdk_pixbuf_new + (GDK_COLORSPACE_RGB, FALSE, 8, + dest_geom->width, dest_geom->height); + + colorv = ((bg_color->red & 0xff00) << 8) | + (bg_color->green & 0xff00) | + ((bg_color->blue & 0xff00) >> 8); + + gdk_pixbuf_composite_color + (src_pixbuf, dest_pixbuf, + 0, 0, + dest_geom->width, + dest_geom->height, + -src_geom->x * scale_x, + -src_geom->y * scale_y, + scale_x, scale_y, + GDK_INTERP_BILINEAR, + alpha, 0, 0, 65536, + colorv, colorv); + } + else if (need_scaling) { + if (dest_pixbuf == NULL) { + dest_pixbuf = gdk_pixbuf_new + (GDK_COLORSPACE_RGB, FALSE, 8, + dest_geom->width, dest_geom->height); + real_dest_x = real_dest_y = 0; + } else { + real_dest_x = dest_geom->x; + real_dest_y = dest_geom->y; + } + + gdk_pixbuf_scale + (src_pixbuf, dest_pixbuf, + real_dest_x, real_dest_y, + dest_geom->width, + dest_geom->height, + real_dest_x - src_geom->x * scale_x, + real_dest_y - src_geom->y * scale_y, + scale_x, scale_y, + GDK_INTERP_BILINEAR); + } + else if (dest_pixbuf != NULL) { + gdk_pixbuf_copy_area + (src_pixbuf, + src_geom->x, src_geom->y, + src_geom->width, + src_geom->height, + dest_pixbuf, + dest_geom->x, dest_geom->y); + } else { + dest_pixbuf = src_pixbuf; + g_object_ref (G_OBJECT (dest_pixbuf)); + } + + return dest_pixbuf; +} + +/* Tile one pixbuf repeatedly onto another, compositing as necessary. Assumes + * that the source pixbuf has already been scaled properly + */ + +static GdkPixbuf * +tile_pixbuf (GdkPixbuf *dest_pixbuf, + GdkPixbuf *src_pixbuf, + GdkRectangle *field_geom, + guint alpha, + GdkColor *bg_color) +{ + gboolean need_composite; + gboolean use_simple; + gdouble cx, cy; + gdouble colorv; + gint pwidth, pheight; + + need_composite = (alpha < 255 || gdk_pixbuf_get_has_alpha (src_pixbuf)); + use_simple = (dest_pixbuf == NULL); + + if (dest_pixbuf == NULL) + dest_pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, field_geom->width, field_geom->height); + + if (need_composite && use_simple) + colorv = ((bg_color->red & 0xff00) << 8) | + (bg_color->green & 0xff00) | + ((bg_color->blue & 0xff00) >> 8); + else + colorv = 0; + + pwidth = gdk_pixbuf_get_width (src_pixbuf); + pheight = gdk_pixbuf_get_height (src_pixbuf); + + for (cy = 0; cy < field_geom->height; cy += pheight) { + for (cx = 0; cx < field_geom->width; cx += pwidth) { + if (need_composite && !use_simple) + gdk_pixbuf_composite + (src_pixbuf, dest_pixbuf, + cx, cy, + MIN (pwidth, field_geom->width - cx), + MIN (pheight, field_geom->height - cy), + cx, cy, + 1.0, 1.0, + GDK_INTERP_BILINEAR, + alpha); + else if (need_composite && use_simple) + gdk_pixbuf_composite_color + (src_pixbuf, dest_pixbuf, + cx, cy, + MIN (pwidth, field_geom->width - cx), + MIN (pheight, field_geom->height - cy), + cx, cy, + 1.0, 1.0, + GDK_INTERP_BILINEAR, + alpha, + 65536, 65536, 65536, + colorv, colorv); + else + gdk_pixbuf_copy_area + (src_pixbuf, + 0, 0, + MIN (pwidth, field_geom->width - cx), + MIN (pheight, field_geom->height - cy), + dest_pixbuf, + cx, cy); + } + } + + return dest_pixbuf; +} + +/* Fill a raw character array with gradient data; the data may then be imported + * into a GdkPixbuf + */ + +static void +fill_gradient (GdkPixbuf *pixbuf, + GdkColor *c1, + GdkColor *c2, + orientation_t orientation) +{ + int i, j; + int dr, dg, db; + int gs1; + int vc = ((orientation == ORIENTATION_HORIZ) || (c1 == c2)); + int w = gdk_pixbuf_get_width (pixbuf); + int h = gdk_pixbuf_get_height (pixbuf); + guchar *b, *row; + guchar *d = gdk_pixbuf_get_pixels (pixbuf); + int rowstride = gdk_pixbuf_get_rowstride (pixbuf); + +#define R1 c1->red +#define G1 c1->green +#define B1 c1->blue +#define R2 c2->red +#define G2 c2->green +#define B2 c2->blue + + dr = R2 - R1; + dg = G2 - G1; + db = B2 - B1; + + gs1 = (orientation == ORIENTATION_VERT) ? h-1 : w-1; + + row = g_new (unsigned char, rowstride); + + if (vc) { + b = row; + for (j = 0; j < w; j++) { + *b++ = (R1 + (j * dr) / gs1) >> 8; + *b++ = (G1 + (j * dg) / gs1) >> 8; + *b++ = (B1 + (j * db) / gs1) >> 8; + } + } + + for (i = 0; i < h; i++) { + if (!vc) { + unsigned char cr, cg, cb; + cr = (R1 + (i * dr) / gs1) >> 8; + cg = (G1 + (i * dg) / gs1) >> 8; + cb = (B1 + (i * db) / gs1) >> 8; + b = row; + for (j = 0; j < w; j++) { + *b++ = cr; + *b++ = cg; + *b++ = cb; + } + } + memcpy (d, row, w * 3); + d += rowstride; + } + +#undef R1 +#undef G1 +#undef B1 +#undef R2 +#undef G2 +#undef B2 + + g_free (row); +} + +/* Boolean predicates to assist optimization and rendering */ + +/* Return TRUE iff the wallpaper filename or enabled settings have changed + * between old_prefs and new_prefs + */ + +static gboolean +need_wallpaper_load_p (const BGApplier *bg_applier, const BGPreferences *prefs) +{ + if (bg_applier->p->last_prefs == NULL) + return TRUE; + else if (prefs->wallpaper_enabled && bg_applier->p->wallpaper_pixbuf == NULL) + return TRUE; + else if (bg_applier->p->last_prefs->wallpaper_enabled != prefs->wallpaper_enabled) + return TRUE; + else if (!bg_applier->p->last_prefs->wallpaper_enabled && !prefs->wallpaper_enabled) + return FALSE; + else if (strcmp (bg_applier->p->last_prefs->wallpaper_filename, prefs->wallpaper_filename)) + return TRUE; + else if (bg_applier->p->last_prefs->wallpaper_type == prefs->wallpaper_type) + return FALSE; + else if (bg_applier->p->last_prefs->wallpaper_type != WPTYPE_TILED && + bg_applier->p->last_prefs->wallpaper_type != WPTYPE_CENTERED) + return TRUE; + else if (prefs->wallpaper_type != WPTYPE_TILED && + prefs->wallpaper_type != WPTYPE_CENTERED) + return TRUE; + else + return FALSE; +} + +/* Return TRUE iff we need to create a new root pixmap */ + +static gboolean +need_root_pixmap_p (const BGApplier *bg_applier, const BGPreferences *prefs) +{ + if (bg_applier->p->pixmap == NULL) + return TRUE; + else if (prefs->wallpaper_enabled == FALSE && prefs->gradient_enabled == FALSE) + return FALSE; + else if (bg_applier->p->last_prefs == NULL) + return TRUE; + else if (bg_applier->p->last_prefs->wallpaper_enabled == FALSE && bg_applier->p->last_prefs->gradient_enabled == FALSE) + return TRUE; + else if (render_small_pixmap_p (bg_applier->p->last_prefs) != render_small_pixmap_p (prefs)) + return TRUE; + else if (!render_small_pixmap_p (bg_applier->p->last_prefs) && + !render_small_pixmap_p (prefs)) + return FALSE; + else if (bg_applier->p->last_prefs->orientation != prefs->orientation) + return TRUE; + else + return FALSE; +} + +/* Return TRUE iff the colors are equal */ + +/* Return TRUE iff the wallpaper completely covers the colors in the given + * bg_preferences structure, assuming we have already loaded the wallpaper pixbuf */ + +static gboolean +wallpaper_full_cover_p (const BGApplier *bg_applier, const BGPreferences *prefs) +{ + gint swidth, sheight; + gint pwidth, pheight; + gdouble asp1, asp2; + + if (bg_applier->p->wallpaper_pixbuf == NULL) + return FALSE; + else if (gdk_pixbuf_get_has_alpha (bg_applier->p->wallpaper_pixbuf)) + return FALSE; + else if (prefs->wallpaper_type == WPTYPE_TILED) + return TRUE; + else if (prefs->wallpaper_type == WPTYPE_STRETCHED) + return TRUE; + + gdk_drawable_get_size (bg_applier->p->root_window, &swidth, &sheight); + pwidth = gdk_pixbuf_get_width (bg_applier->p->wallpaper_pixbuf); + pheight = gdk_pixbuf_get_height (bg_applier->p->wallpaper_pixbuf); + + if (prefs->wallpaper_type == WPTYPE_CENTERED) { + if (pwidth >= swidth && pheight >= sheight) + return TRUE; + else + return FALSE; + } + else if (prefs->wallpaper_type == WPTYPE_SCALED) { + asp1 = (gdouble) swidth / (gdouble) sheight; + asp2 = (gdouble) pwidth / (gdouble) pheight; + + if (swidth * (asp1 - asp2) < 1 && swidth * (asp2 - asp1) < 1) + return TRUE; + else + return FALSE; + } + + return FALSE; +} + +/* Return TRUE if we can optimize the rendering by using a small thin pixmap */ + +static gboolean +render_small_pixmap_p (const BGPreferences *prefs) +{ + return prefs->gradient_enabled && !prefs->wallpaper_enabled; +} + +/* Create a persistent pixmap. We create a separate display + * and set the closedown mode on it to RetainPermanent + */ +static GdkPixmap * +make_root_pixmap (GdkScreen *screen, gint width, gint height) +{ + Display *display; + char *display_name; + Pixmap result; + GdkPixmap *gdk_pixmap; + int screen_num; + + screen_num = gdk_screen_get_number (screen); + + gdk_flush (); + + display_name = DisplayString (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ())); + + display = XOpenDisplay (display_name); + + if (display == NULL) { + g_warning ("Unable to open display '%s' when setting background pixmap\n", + (display_name) ? display_name : "NULL"); + return NULL; + } + + XSetCloseDownMode (display, RetainPermanent); + + result = XCreatePixmap (display, + RootWindow (display, screen_num), + width, height, + DefaultDepth (display, screen_num)); + + XCloseDisplay (display); + + gdk_pixmap = gdk_pixmap_foreign_new (result); + gdk_drawable_set_colormap (GDK_DRAWABLE (gdk_pixmap), + gdk_drawable_get_colormap (gdk_screen_get_root_window (screen))); + + return gdk_pixmap; +} + +/* Set the root pixmap, and properties pointing to it. We + * do this atomically with XGrabServer to make sure that + * we won't leak the pixmap if somebody else it setting + * it at the same time. (This assumes that they follow the + * same conventions we do) + */ + +static void +set_root_pixmap (GdkPixmap *pixmap, GdkScreen *screen) +{ + Atom type; + gulong nitems, bytes_after; + gint format; + guchar *data_esetroot; + Pixmap pixmap_id; + Display *display; + int screen_num; + + /* Final check to see if nautilus is running. If it is, we don't + touch the root pixmap at all. */ + if (is_nautilus_running ()) + return; + + screen_num = gdk_screen_get_number (screen); + + if (pixmap != NULL) + pixmap_id = GDK_WINDOW_XWINDOW (pixmap); + else + pixmap_id = 0; + + display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); + + XGrabServer (display); + + XGetWindowProperty (display, RootWindow (display, screen_num), + XInternAtom (display, "ESETROOT_PMAP_ID", False), + 0L, 1L, False, XA_PIXMAP, + &type, &format, &nitems, &bytes_after, + &data_esetroot); + + if (type == XA_PIXMAP) { + if (format == 32 && nitems == 1) { + Pixmap old_pixmap; + + old_pixmap = *((Pixmap *) data_esetroot); + + if (pixmap != NULL && old_pixmap != pixmap_id) + XKillClient (display, old_pixmap); + else if (pixmap == NULL) + pixmap_id = old_pixmap; + } + + XFree (data_esetroot); + } + + if (pixmap != NULL) { + XChangeProperty (display, RootWindow (display, screen_num), + XInternAtom (display, "ESETROOT_PMAP_ID", FALSE), + XA_PIXMAP, 32, PropModeReplace, + (guchar *) &pixmap_id, 1); + XChangeProperty (display, RootWindow (display, screen_num), + XInternAtom (display, "_XROOTPMAP_ID", FALSE), + XA_PIXMAP, 32, PropModeReplace, + (guchar *) &pixmap_id, 1); + + XSetWindowBackgroundPixmap (display, RootWindow (display, screen_num), + pixmap_id); + } else if (pixmap == NULL) { + XDeleteProperty (display, RootWindow (display, screen_num), + XInternAtom (display, "ESETROOT_PMAP_ID", FALSE)); + XDeleteProperty (display, RootWindow (display, screen_num), + XInternAtom (display, "_XROOTPMAP_ID", FALSE)); + } + + XClearWindow (display, RootWindow (display, screen_num)); + XUngrabServer (display); + XFlush (display); +} + +static gboolean +is_nautilus_running (void) +{ + Atom window_id_atom; + Window nautilus_xid; + Atom actual_type; + int actual_format; + unsigned long nitems, bytes_after; + unsigned char *data; + int retval; + Atom wmclass_atom; + gboolean running; + gint error; + + window_id_atom = XInternAtom (GDK_DISPLAY (), + "NAUTILUS_DESKTOP_WINDOW_ID", True); + + if (window_id_atom == None) return FALSE; + + retval = XGetWindowProperty (GDK_DISPLAY (), GDK_ROOT_WINDOW (), + window_id_atom, 0, 1, False, XA_WINDOW, + &actual_type, &actual_format, &nitems, + &bytes_after, &data); + + if (data != NULL) { + nautilus_xid = *(Window *) data; + XFree (data); + } else { + return FALSE; + } + + if (actual_type != XA_WINDOW) return FALSE; + if (actual_format != 32) return FALSE; + + wmclass_atom = XInternAtom (GDK_DISPLAY (), "WM_CLASS", False); + + gdk_error_trap_push (); + + retval = XGetWindowProperty (GDK_DISPLAY (), nautilus_xid, + wmclass_atom, 0, 24, False, XA_STRING, + &actual_type, &actual_format, &nitems, + &bytes_after, &data); + + error = gdk_error_trap_pop (); + + if (error == BadWindow) return FALSE; + + if (actual_type == XA_STRING && + nitems == 24 && + bytes_after == 0 && + actual_format == 8 && + data != NULL && + !strcmp ((char *)data, "desktop_window") && + !strcmp ((char *)data + strlen ((char *)data) + 1, "Nautilus")) + running = TRUE; + else + running = FALSE; + + if (data != NULL) + XFree (data); + + return running; +} + +static gboolean +cleanup_cb (BGApplier *bg_applier) +{ + g_message ("cleanup_cb: Enter"); + + if (bg_applier->p->wallpaper_pixbuf != NULL) { + g_object_unref (G_OBJECT (bg_applier->p->wallpaper_pixbuf)); + bg_applier->p->wallpaper_pixbuf = NULL; + } + + if (bg_applier->p->pixbuf != NULL) { + g_object_unref (G_OBJECT (bg_applier->p->pixbuf)); + bg_applier->p->pixbuf = NULL; + } + + bg_applier->p->timeout = 0; + + return FALSE; +} + +static void +preview_realized_cb (GtkWidget *preview, BGApplier *bg_applier) +{ + GdkPixmap *pixmap; + + /* Only draw clean image if no pref set yet */ + if (bg_applier->p->last_prefs) + return; + + gtk_image_get_pixmap (GTK_IMAGE (preview), &pixmap, NULL); + if (!pixmap) { + pixmap = gdk_pixmap_new (preview->window, + bg_applier->p->render_geom.width, + bg_applier->p->render_geom.height, + -1); + gtk_image_set_from_pixmap (GTK_IMAGE (preview), pixmap, NULL); + } + + gdk_draw_rectangle (pixmap, + preview->style->bg_gc[preview->state], + TRUE, + bg_applier->p->render_geom.x, + bg_applier->p->render_geom.y, + bg_applier->p->render_geom.width, + bg_applier->p->render_geom.height); +} + diff --git a/gui/simple-greeter/libbackground/applier.h b/gui/simple-greeter/libbackground/applier.h new file mode 100644 index 00000000..e058123f --- /dev/null +++ b/gui/simple-greeter/libbackground/applier.h @@ -0,0 +1,76 @@ +/* -*- mode: c; style: linux -*- */ + +/* applier.h + * Copyright (C) 2000 Helix Code, Inc. + * + * Written by Bradford Hovinen <hovinen@helixcode.com> + * + * 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, 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 __APPLIER_H +#define __APPLIER_H + +#include <gtk/gtk.h> +#include <gdk-pixbuf/gdk-pixbuf.h> + +#include <X11/Xlib.h> + +#include "preferences.h" + +#define BG_APPLIER(obj) G_TYPE_CHECK_INSTANCE_CAST (obj, bg_applier_get_type (), BGApplier) +#define BG_APPLIER_CLASS(klass) G_TYPE_CHECK_CLASS_CAST (klass, bg_applier_get_type (), BGApplierClass) +#define IS_BG_APPLIER(obj) G_TYPE_CHECK_INSTANCE_TYPE (obj, bg_applier_get_type ()) + +typedef struct _BGApplier BGApplier; +typedef struct _BGApplierClass BGApplierClass; + +typedef struct _BGApplierPrivate BGApplierPrivate; + +typedef enum _BGApplierType { + BG_APPLIER_ROOT, BG_APPLIER_PREVIEW +} BGApplierType; + +struct _BGApplier +{ + GObject object; + BGApplierPrivate *p; +}; + +struct _BGApplierClass +{ + GObjectClass klass; +}; + +GType bg_applier_get_type (void); + +GObject *bg_applier_new (BGApplierType type); +GObject *bg_applier_new_at_size (BGApplierType type, + const guint width, + const guint height); +GObject *bg_applier_new_for_screen (BGApplierType type, + GdkScreen *screen); + +void bg_applier_apply_prefs (BGApplier *bg_applier, + const BGPreferences *prefs); + +gboolean bg_applier_render_color_p (const BGApplier *bg_applier, + const BGPreferences *prefs); + +GtkWidget *bg_applier_get_preview_widget (BGApplier *bg_applier); +GdkPixbuf *bg_applier_get_wallpaper_pixbuf (BGApplier *bg_applier); + +#endif /* __APPLIER_H */ diff --git a/gui/simple-greeter/libbackground/preferences.c b/gui/simple-greeter/libbackground/preferences.c new file mode 100644 index 00000000..9090657f --- /dev/null +++ b/gui/simple-greeter/libbackground/preferences.c @@ -0,0 +1,510 @@ +/* -*- mode: c; style: linux -*- */ + +/* preferences.c + * Copyright (C) 2001 Ximian, Inc. + * + * Written by Bradford Hovinen <hovinen@ximian.com> + * + * 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, 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 <stdlib.h> +#include <string.h> + +#include <glib.h> +#include <gdk/gdk.h> + +#include "preferences.h" + +static GObjectClass *parent_class; + +static void bg_preferences_init (BGPreferences *prefs, + BGPreferencesClass *class); +static void bg_preferences_class_init (BGPreferencesClass *class); + +static void bg_preferences_finalize (GObject *object); + +static GdkColor *read_color_from_string (const gchar *string); +static orientation_t read_orientation_from_string (const gchar *string); +static wallpaper_type_t read_wptype_from_string (const gchar *string); + +static GEnumValue _bg_wptype_values[] = { + { WPTYPE_TILED, "WPTYPE_TILED", "wallpaper"}, + { WPTYPE_CENTERED, "WPTYPE_CENTERED", "centered"}, + { WPTYPE_SCALED, "WPTYPE_SCALED", "scaled"}, + { WPTYPE_STRETCHED, "WPTYPE_STRETCHED", "stretched"}, + { WPTYPE_ZOOM, "WPTYPE_ZOOM", "zoom"}, + { WPTYPE_NONE, "WPTYPE_NONE", "none"}, + { 0, NULL, NULL } +}; + +static GEnumValue _bg_orientation_values[] = { + { ORIENTATION_SOLID, "ORIENTATION_SOLID", "solid"}, + { ORIENTATION_HORIZ, "ORIENTATION_HORIZ", "horizontal-gradient"}, + { ORIENTATION_VERT, "ORIENTATION_VERT", "vertical-gradient"}, + { 0, NULL, NULL } +}; + +GType +bg_preferences_wptype_get_type (void) +{ + static GType type = 0; + + if (!type) + { + type = g_enum_register_static ("BgPreferencesWptype", + _bg_wptype_values); + } + + return type; +} + +GType +bg_preferences_orientation_get_type (void) +{ + static GType type = 0; + + if (!type) + { + type = g_enum_register_static ("BgPreferencesOrientation", + _bg_orientation_values); + } + + return type; +} + +GType +bg_preferences_get_type (void) +{ + static GType bg_preferences_type = 0; + + if (!bg_preferences_type) { + GTypeInfo bg_preferences_info = { + sizeof (BGPreferencesClass), + NULL, + NULL, + (GClassInitFunc) bg_preferences_class_init, + NULL, + NULL, + sizeof (BGPreferences), + 0, + (GInstanceInitFunc) bg_preferences_init, + }; + + bg_preferences_type = + g_type_register_static (G_TYPE_OBJECT, "BGPreferences", &bg_preferences_info, 0); + } + + return bg_preferences_type; +} + +static void +bg_preferences_init (BGPreferences *prefs, + BGPreferencesClass *class) +{ + prefs->frozen = FALSE; + + /* Load default values */ + prefs->color1 = read_color_from_string ("#39374b"); + prefs->color2 = read_color_from_string ("#42528f"); + prefs->enabled = TRUE; + prefs->wallpaper_enabled = FALSE; + prefs->gradient_enabled = TRUE; + prefs->orientation = ORIENTATION_VERT; + prefs->wallpaper_type = WPTYPE_TILED; + prefs->wallpaper_filename = NULL; + prefs->wallpaper_sel_path = g_strdup (g_get_home_dir ()); + prefs->auto_apply = TRUE; + prefs->wallpapers = NULL; + prefs->adjust_opacity = TRUE; + prefs->opacity = 255; +} + +static void +bg_preferences_class_init (BGPreferencesClass *class) +{ + GObjectClass *object_class; + + object_class = (GObjectClass *) class; + object_class->finalize = bg_preferences_finalize; + + parent_class = + G_OBJECT_CLASS (g_type_class_ref (G_TYPE_OBJECT)); +} + +GObject * +bg_preferences_new (void) +{ + GObject *object; + + object = g_object_new (bg_preferences_get_type (), NULL); + BG_PREFERENCES (object)->enabled = TRUE; + + return object; +} + +GObject * +bg_preferences_clone (const BGPreferences *prefs) +{ + GObject *object; + BGPreferences *new_prefs; + + g_return_val_if_fail (prefs != NULL, NULL); + g_return_val_if_fail (IS_BG_PREFERENCES (prefs), NULL); + + object = bg_preferences_new (); + + new_prefs = BG_PREFERENCES (object); + + new_prefs->enabled = prefs->enabled; + new_prefs->gradient_enabled = prefs->gradient_enabled; + new_prefs->wallpaper_enabled = prefs->wallpaper_enabled; + new_prefs->orientation = prefs->orientation; + new_prefs->wallpaper_type = prefs->wallpaper_type; + + if (new_prefs->color1 != NULL) + gdk_color_free (new_prefs->color1); + new_prefs->color1 = (prefs->color1 != NULL) + ? gdk_color_copy (prefs->color1) : NULL; + + if (new_prefs->color2 != NULL) + gdk_color_free (new_prefs->color2); + new_prefs->color2 = (prefs->color2 != NULL) + ? gdk_color_copy (prefs->color2) : NULL; + + if (new_prefs->wallpaper_filename != NULL) + g_free (new_prefs->wallpaper_filename); + new_prefs->wallpaper_filename = g_strdup (prefs->wallpaper_filename); + + if (new_prefs->wallpaper_sel_path != NULL) + g_free (new_prefs->wallpaper_sel_path); + new_prefs->wallpaper_sel_path = g_strdup (prefs->wallpaper_sel_path);; + + new_prefs->auto_apply = prefs->auto_apply; + new_prefs->adjust_opacity = prefs->adjust_opacity; + new_prefs->opacity = prefs->opacity; + + return object; +} + +static void +bg_preferences_finalize (GObject *object) +{ + BGPreferences *prefs; + + g_return_if_fail (object != NULL); + g_return_if_fail (IS_BG_PREFERENCES (object)); + + prefs = BG_PREFERENCES (object); + + g_free (prefs->wallpaper_filename); + prefs->wallpaper_filename = NULL; + + g_free (prefs->wallpaper_sel_path); + prefs->wallpaper_sel_path = NULL; + + if (prefs->color1 != NULL) { + gdk_color_free (prefs->color1); + prefs->color1 = NULL; + } + if (prefs->color2 != NULL) { + gdk_color_free (prefs->color2); + prefs->color2 = NULL; + } + + parent_class->finalize (object); +} + +void +bg_preferences_load (BGPreferences *prefs) +{ + GConfClient *client; + GError *error = NULL; + char *tmp; + + g_return_if_fail (prefs != NULL); + g_return_if_fail (IS_BG_PREFERENCES (prefs)); + + client = gconf_client_get_default (); + + prefs->enabled = gconf_client_get_bool (client, BG_PREFERENCES_DRAW_BACKGROUND, &error); + tmp = gconf_client_get_string (client, BG_PREFERENCES_PICTURE_FILENAME, &error); + if (tmp) { + if (g_utf8_validate (tmp, -1, NULL) && + g_file_test (tmp, G_FILE_TEST_EXISTS)) + prefs->wallpaper_filename = g_strdup (tmp); + else + prefs->wallpaper_filename = g_filename_from_utf8 (tmp, -1, NULL, + NULL, NULL); + } + g_free (tmp); + + if (prefs->color1 != NULL) + gdk_color_free (prefs->color1); + tmp = gconf_client_get_string (client, BG_PREFERENCES_PRIMARY_COLOR, &error); + prefs->color1 = read_color_from_string (tmp); + g_free (tmp); + + if (prefs->color2 != NULL) + gdk_color_free (prefs->color2); + tmp = gconf_client_get_string (client, BG_PREFERENCES_SECONDARY_COLOR, &error); + prefs->color2 = read_color_from_string (tmp); + g_free (tmp); + + prefs->opacity = gconf_client_get_int (client, BG_PREFERENCES_PICTURE_OPACITY, &error); + if (prefs->opacity >= 100 || prefs->opacity < 0) + prefs->adjust_opacity = FALSE; + + tmp = gconf_client_get_string (client, BG_PREFERENCES_COLOR_SHADING_TYPE, &error); + prefs->orientation = read_orientation_from_string (tmp); + g_free (tmp); + + if (prefs->orientation == ORIENTATION_SOLID) + prefs->gradient_enabled = FALSE; + else + prefs->gradient_enabled = TRUE; + + tmp = gconf_client_get_string (client, BG_PREFERENCES_PICTURE_OPTIONS, &error); + prefs->wallpaper_type = read_wptype_from_string (tmp); + g_free (tmp); + + if (prefs->wallpaper_type == WPTYPE_UNSET) { + prefs->wallpaper_enabled = FALSE; + prefs->wallpaper_type = WPTYPE_CENTERED; + } else { + prefs->wallpaper_enabled = TRUE; + } + + g_object_unref (client); +} + +/* Parse the event name given (the event being notification of a property having + * changed and apply that change to the bg_preferences structure. Eliminates the + * need to reload the structure entirely on every event notification + */ + +void +bg_preferences_merge_entry (BGPreferences *prefs, + const GConfEntry *entry) +{ + const GConfValue *value = gconf_entry_get_value (entry); + + g_return_if_fail (prefs != NULL); + g_return_if_fail (IS_BG_PREFERENCES (prefs)); + + if (!strcmp (entry->key, BG_PREFERENCES_PICTURE_OPTIONS)) { + wallpaper_type_t wallpaper_type = read_wptype_from_string (gconf_value_get_string (value)); + if (wallpaper_type == WPTYPE_UNSET) { + prefs->wallpaper_enabled = FALSE; + } else { + prefs->wallpaper_type = wallpaper_type; + prefs->wallpaper_enabled = TRUE; + } + } + else if (!strcmp (entry->key, BG_PREFERENCES_PICTURE_FILENAME)) { + const char *tmp; + + tmp = gconf_value_get_string (value); + if (g_utf8_validate (tmp, -1, NULL) && + g_file_test (tmp, G_FILE_TEST_EXISTS)) + prefs->wallpaper_filename = g_strdup (tmp); + else + prefs->wallpaper_filename = g_filename_from_utf8 (tmp, -1, + NULL, + NULL, + NULL); + + if (prefs->wallpaper_filename != NULL && + strcmp (prefs->wallpaper_filename, "") != 0 && + strcmp (prefs->wallpaper_filename, "(none)") != 0) + prefs->wallpaper_enabled = TRUE; + else + prefs->wallpaper_enabled = FALSE; + } + else if (!strcmp (entry->key, BG_PREFERENCES_PRIMARY_COLOR)) { + if (prefs->color1 != NULL) + gdk_color_free (prefs->color1); + prefs->color1 = read_color_from_string (gconf_value_get_string (value)); + } + else if (!strcmp (entry->key, BG_PREFERENCES_SECONDARY_COLOR)) { + if (prefs->color2 != NULL) + gdk_color_free (prefs->color2); + prefs->color2 = read_color_from_string (gconf_value_get_string (value)); + } + else if (!strcmp (entry->key, BG_PREFERENCES_PICTURE_OPACITY)) { + prefs->opacity = gconf_value_get_int (value); + + if (prefs->opacity >= 100) + prefs->adjust_opacity = FALSE; + } + else if (!strcmp (entry->key, BG_PREFERENCES_COLOR_SHADING_TYPE)) { + prefs->orientation = read_orientation_from_string (gconf_value_get_string (value)); + + if (prefs->orientation == ORIENTATION_SOLID) + prefs->gradient_enabled = FALSE; + else + prefs->gradient_enabled = TRUE; + } + else if (!strcmp (entry->key, BG_PREFERENCES_DRAW_BACKGROUND)) { + if (gconf_value_get_bool (value) && + (prefs->wallpaper_filename != NULL) && + strcmp (prefs->wallpaper_filename, "") != 0 && + strcmp (prefs->wallpaper_filename, "(none)") != 0) + prefs->enabled = TRUE; + else + prefs->enabled = FALSE; + } else { + g_warning ("%s: Unknown property: %s", G_GNUC_FUNCTION, entry->key); + } +} + +static wallpaper_type_t +read_wptype_from_string (const gchar *string) +{ + wallpaper_type_t type = WPTYPE_UNSET; + + if (string) { + if (!strncmp (string, "wallpaper", sizeof ("wallpaper"))) { + type = WPTYPE_TILED; + } else if (!strncmp (string, "centered", sizeof ("centered"))) { + type = WPTYPE_CENTERED; + } else if (!strncmp (string, "scaled", sizeof ("scaled"))) { + type = WPTYPE_SCALED; + } else if (!strncmp (string, "stretched", sizeof ("stretched"))) { + type = WPTYPE_STRETCHED; + } else if (!strncmp (string, "zoom", sizeof ("zoom"))) { + type = WPTYPE_ZOOM; + } + } + + return type; +} + +static orientation_t +read_orientation_from_string (const gchar *string) +{ + orientation_t type = ORIENTATION_SOLID; + + if (string) { + if (!strncmp (string, "vertical-gradient", sizeof ("vertical-gradient"))) { + type = ORIENTATION_VERT; + } else if (!strncmp (string, "horizontal-gradient", sizeof ("horizontal-gradient"))) { + type = ORIENTATION_HORIZ; + } + } + + return type; +} + +static GdkColor * +read_color_from_string (const gchar *string) +{ + GdkColor color; + + /* If all else fails use black */ + if (string == NULL || !gdk_color_parse (string, &color)) + gdk_color_parse ("black", &color); + gdk_rgb_find_color (gdk_rgb_get_colormap (), &color); + return gdk_color_copy (&color); +} + +const gchar* +bg_preferences_get_wptype_as_string (wallpaper_type_t wp) +{ + switch (wp) + { + case WPTYPE_TILED: + return "wallpaper"; + case WPTYPE_CENTERED: + return "centered"; + case WPTYPE_SCALED: + return "scaled"; + case WPTYPE_STRETCHED: + return "stretched"; + case WPTYPE_ZOOM: + return "zoom"; + case WPTYPE_NONE: + return "none"; + case WPTYPE_UNSET: + return NULL; + } + + return NULL; +} + +const gchar* +bg_preferences_get_orientation_as_string (orientation_t o) +{ + switch (o) + { + case ORIENTATION_SOLID: + return "solid"; + case ORIENTATION_HORIZ: + return "horizontal-gradient"; + case ORIENTATION_VERT: + return "vertical-gradient"; + } + + return NULL; +} + +void +bg_preferences_save (BGPreferences *prefs) +{ + GConfChangeSet *cs; + gchar *tmp; + GConfClient *client; + + g_return_if_fail (prefs != NULL); + g_return_if_fail (IS_BG_PREFERENCES (prefs)); + + client = gconf_client_get_default(); + + cs = gconf_change_set_new (); + gconf_change_set_set_bool (cs, BG_PREFERENCES_DRAW_BACKGROUND, prefs->enabled); + if (prefs->wallpaper_enabled) + gconf_change_set_set_string (cs, BG_PREFERENCES_PICTURE_OPTIONS, bg_preferences_get_wptype_as_string (prefs->wallpaper_type)); + else + gconf_change_set_set_string (cs, BG_PREFERENCES_PICTURE_OPTIONS, "none"); + + gconf_change_set_set_string (cs, BG_PREFERENCES_PICTURE_FILENAME, prefs->wallpaper_filename); + + tmp = g_strdup_printf ("#%02x%02x%02x", + prefs->color1->red >> 8, + prefs->color1->green >> 8, + prefs->color1->blue >> 8); + gconf_change_set_set_string (cs, BG_PREFERENCES_PRIMARY_COLOR, tmp); + g_free (tmp); + + tmp = g_strdup_printf ("#%02x%02x%02x", + prefs->color2->red >> 8, + prefs->color2->green >> 8, + prefs->color2->blue >> 8); + gconf_change_set_set_string (cs, BG_PREFERENCES_SECONDARY_COLOR, tmp); + g_free (tmp); + + gconf_change_set_set_string (cs, BG_PREFERENCES_COLOR_SHADING_TYPE, bg_preferences_get_orientation_as_string (prefs->orientation)); + + gconf_client_commit_change_set (client, cs, TRUE, NULL); + gconf_change_set_unref (cs); + g_object_unref (client); +} + + diff --git a/gui/simple-greeter/libbackground/preferences.h b/gui/simple-greeter/libbackground/preferences.h new file mode 100644 index 00000000..30fb7df1 --- /dev/null +++ b/gui/simple-greeter/libbackground/preferences.h @@ -0,0 +1,108 @@ +/* -*- mode: c; style: linux -*- */ + +/* preferences.h + * Copyright (C) 2000 Helix Code, Inc. + * + * Written by Bradford Hovinen <hovinen@helixcode.com> + * + * 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, 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 __BGPREFERENCES_H +#define __BGPREFERENCES_H + +#include <glib-object.h> +#include <gdk-pixbuf/gdk-pixbuf.h> +#include <gconf/gconf-client.h> + +#define BG_PREFERENCES(obj) G_TYPE_CHECK_INSTANCE_CAST (obj, bg_preferences_get_type (), BGPreferences) +#define BG_PREFERENCES_CLASS(klass) G_TYPE_CHECK_CLASS_CAST (klass, bg_preferences_get_type (), BGPreferencesClass) +#define IS_BG_PREFERENCES(obj) G_TYPE_CHECK_INSTANCE_TYPE (obj, bg_preferences_get_type ()) + +#define BG_PREFERENCES_DRAW_BACKGROUND "/desktop/gnome/background/draw_background" +#define BG_PREFERENCES_PRIMARY_COLOR "/desktop/gnome/background/primary_color" +#define BG_PREFERENCES_SECONDARY_COLOR "/desktop/gnome/background/secondary_color" +#define BG_PREFERENCES_COLOR_SHADING_TYPE "/desktop/gnome/background/color_shading_type" +#define BG_PREFERENCES_PICTURE_OPTIONS "/desktop/gnome/background/picture_options" +#define BG_PREFERENCES_PICTURE_OPACITY "/desktop/gnome/background/picture_opacity" +#define BG_PREFERENCES_PICTURE_FILENAME "/desktop/gnome/background/picture_filename" + + +typedef struct _BGPreferences BGPreferences; +typedef struct _BGPreferencesClass BGPreferencesClass; + +typedef enum _orientation_t { + ORIENTATION_SOLID = 0, + ORIENTATION_HORIZ, + ORIENTATION_VERT +} orientation_t; + +typedef enum _wallpaper_type_t { + WPTYPE_TILED = 0, WPTYPE_CENTERED, WPTYPE_SCALED, + WPTYPE_STRETCHED, WPTYPE_ZOOM, WPTYPE_NONE, + WPTYPE_UNSET +} wallpaper_type_t; + +struct _BGPreferences +{ + GObject object; + + gint frozen; + gboolean auto_apply; + guint timeout_id; + + gboolean enabled; + gboolean gradient_enabled; + gboolean wallpaper_enabled; + orientation_t orientation; + wallpaper_type_t wallpaper_type; + + GdkColor *color1; + GdkColor *color2; + + gchar *wallpaper_filename; + gchar *wallpaper_sel_path; + + GSList *wallpapers; + + gboolean adjust_opacity; + gint opacity; +}; + +struct _BGPreferencesClass +{ + GObjectClass klass; +}; + +GType bg_preferences_get_type (void); + +GObject *bg_preferences_new (void); +GObject *bg_preferences_clone (const BGPreferences *prefs); + +void bg_preferences_load (BGPreferences *prefs); + +void bg_preferences_merge_entry (BGPreferences *prefs, + const GConfEntry *entry); + +void bg_preferences_save (BGPreferences *prefs); + +const gchar *bg_preferences_get_wptype_as_string (wallpaper_type_t wp); +const gchar *bg_preferences_get_orientation_as_string (orientation_t o); +GType bg_preferences_wptype_get_type (void); +GType bg_preferences_orientation_get_type (void); + + +#endif /* __PREFERENCES_H */ diff --git a/gui/simple-greeter/libnotificationarea/na-marshal.c b/gui/simple-greeter/libnotificationarea/na-marshal.c deleted file mode 100644 index 7cbaf722..00000000 --- a/gui/simple-greeter/libnotificationarea/na-marshal.c +++ /dev/null @@ -1,165 +0,0 @@ -#include "na-marshal.h" - -#include <glib-object.h> - - -#ifdef G_ENABLE_DEBUG -#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) -#define g_marshal_value_peek_char(v) g_value_get_char (v) -#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) -#define g_marshal_value_peek_int(v) g_value_get_int (v) -#define g_marshal_value_peek_uint(v) g_value_get_uint (v) -#define g_marshal_value_peek_long(v) g_value_get_long (v) -#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v) -#define g_marshal_value_peek_int64(v) g_value_get_int64 (v) -#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v) -#define g_marshal_value_peek_enum(v) g_value_get_enum (v) -#define g_marshal_value_peek_flags(v) g_value_get_flags (v) -#define g_marshal_value_peek_float(v) g_value_get_float (v) -#define g_marshal_value_peek_double(v) g_value_get_double (v) -#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v) -#define g_marshal_value_peek_param(v) g_value_get_param (v) -#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v) -#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v) -#define g_marshal_value_peek_object(v) g_value_get_object (v) -#else /* !G_ENABLE_DEBUG */ -/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API. - * Do not access GValues directly in your code. Instead, use the - * g_value_get_*() functions - */ -#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int -#define g_marshal_value_peek_char(v) (v)->data[0].v_int -#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint -#define g_marshal_value_peek_int(v) (v)->data[0].v_int -#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint -#define g_marshal_value_peek_long(v) (v)->data[0].v_long -#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong -#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 -#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 -#define g_marshal_value_peek_enum(v) (v)->data[0].v_long -#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong -#define g_marshal_value_peek_float(v) (v)->data[0].v_float -#define g_marshal_value_peek_double(v) (v)->data[0].v_double -#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer -#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer -#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer -#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer -#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer -#endif /* !G_ENABLE_DEBUG */ - - -/* VOID:OBJECT,OBJECT (na-marshal.list:1) */ -void -_na_marshal_VOID__OBJECT_OBJECT (GClosure *closure, - GValue *return_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data) -{ - typedef void (*GMarshalFunc_VOID__OBJECT_OBJECT) (gpointer data1, - gpointer arg_1, - gpointer arg_2, - gpointer data2); - register GMarshalFunc_VOID__OBJECT_OBJECT callback; - register GCClosure *cc = (GCClosure*) closure; - register gpointer data1, data2; - - g_return_if_fail (n_param_values == 3); - - if (G_CCLOSURE_SWAP_DATA (closure)) - { - data1 = closure->data; - data2 = g_value_peek_pointer (param_values + 0); - } - else - { - data1 = g_value_peek_pointer (param_values + 0); - data2 = closure->data; - } - callback = (GMarshalFunc_VOID__OBJECT_OBJECT) (marshal_data ? marshal_data : cc->callback); - - callback (data1, - g_marshal_value_peek_object (param_values + 1), - g_marshal_value_peek_object (param_values + 2), - data2); -} - -/* VOID:OBJECT,STRING,LONG,LONG (na-marshal.list:2) */ -void -_na_marshal_VOID__OBJECT_STRING_LONG_LONG (GClosure *closure, - GValue *return_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data) -{ - typedef void (*GMarshalFunc_VOID__OBJECT_STRING_LONG_LONG) (gpointer data1, - gpointer arg_1, - gpointer arg_2, - glong arg_3, - glong arg_4, - gpointer data2); - register GMarshalFunc_VOID__OBJECT_STRING_LONG_LONG callback; - register GCClosure *cc = (GCClosure*) closure; - register gpointer data1, data2; - - g_return_if_fail (n_param_values == 5); - - if (G_CCLOSURE_SWAP_DATA (closure)) - { - data1 = closure->data; - data2 = g_value_peek_pointer (param_values + 0); - } - else - { - data1 = g_value_peek_pointer (param_values + 0); - data2 = closure->data; - } - callback = (GMarshalFunc_VOID__OBJECT_STRING_LONG_LONG) (marshal_data ? marshal_data : cc->callback); - - callback (data1, - g_marshal_value_peek_object (param_values + 1), - g_marshal_value_peek_string (param_values + 2), - g_marshal_value_peek_long (param_values + 3), - g_marshal_value_peek_long (param_values + 4), - data2); -} - -/* VOID:OBJECT,LONG (na-marshal.list:3) */ -void -_na_marshal_VOID__OBJECT_LONG (GClosure *closure, - GValue *return_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data) -{ - typedef void (*GMarshalFunc_VOID__OBJECT_LONG) (gpointer data1, - gpointer arg_1, - glong arg_2, - gpointer data2); - register GMarshalFunc_VOID__OBJECT_LONG callback; - register GCClosure *cc = (GCClosure*) closure; - register gpointer data1, data2; - - g_return_if_fail (n_param_values == 3); - - if (G_CCLOSURE_SWAP_DATA (closure)) - { - data1 = closure->data; - data2 = g_value_peek_pointer (param_values + 0); - } - else - { - data1 = g_value_peek_pointer (param_values + 0); - data2 = closure->data; - } - callback = (GMarshalFunc_VOID__OBJECT_LONG) (marshal_data ? marshal_data : cc->callback); - - callback (data1, - g_marshal_value_peek_object (param_values + 1), - g_marshal_value_peek_long (param_values + 2), - data2); -} - diff --git a/gui/simple-greeter/libnotificationarea/na-marshal.h b/gui/simple-greeter/libnotificationarea/na-marshal.h deleted file mode 100644 index 07918a11..00000000 --- a/gui/simple-greeter/libnotificationarea/na-marshal.h +++ /dev/null @@ -1,36 +0,0 @@ - -#ifndef ___na_marshal_MARSHAL_H__ -#define ___na_marshal_MARSHAL_H__ - -#include <glib-object.h> - -G_BEGIN_DECLS - -/* VOID:OBJECT,OBJECT (na-marshal.list:1) */ -extern void _na_marshal_VOID__OBJECT_OBJECT (GClosure *closure, - GValue *return_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data); - -/* VOID:OBJECT,STRING,LONG,LONG (na-marshal.list:2) */ -extern void _na_marshal_VOID__OBJECT_STRING_LONG_LONG (GClosure *closure, - GValue *return_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data); - -/* VOID:OBJECT,LONG (na-marshal.list:3) */ -extern void _na_marshal_VOID__OBJECT_LONG (GClosure *closure, - GValue *return_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data); - -G_END_DECLS - -#endif /* ___na_marshal_MARSHAL_H__ */ - |