nautilus/libnautilus-private/nautilus-directory-background.c
Mike Engber 3cb6510f2a reviewed by: John Sullivan
reviewed by: John Sullivan

	* libnautilus-extensions/nautilus-directory-background.c:
	(theme_image_path_to_uri),
	(nautilus_file_background_get_default_settings_for_theme),
	(nautilus_file_background_get_default_settings),
	(nautilus_file_background_read_desktop_settings),
	(nautilus_file_background_write_desktop_settings),
	(nautilus_file_background_is_set):
	* libnautilus-extensions/nautilus-theme.c:
	(nautilus_theme_get_theme_data_from_theme),
	(nautilus_theme_get_theme_data):
	* libnautilus-extensions/nautilus-theme.h:
	The desktop can now be reset to the "default" meaning when
	you change themes it will use the default desktop setting
	for the new theme - bug 5730.
2001-01-18 23:38:23 +00:00

1038 lines
36 KiB
C

/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
/*
nautilus-directory-background.c: Helper for the background of a widget
that is viewing a particular location.
Copyright (C) 2000 Eazel, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public
License along with this program; if not, write to the
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
Author: Darin Adler <darin@eazel.com>
*/
#include <config.h>
#include "nautilus-directory-background.h"
#include "libnautilus-extensions/nautilus-gdk-extensions.h"
#include "nautilus-background.h"
#include "nautilus-global-preferences.h"
#include "nautilus-metadata.h"
#include "nautilus-file-attributes.h"
#include "nautilus-string.h"
#include "nautilus-theme.h"
#include <X11/Xatom.h>
#include <gdk/gdkx.h>
#include <gtk/gtkmain.h>
#include <gtk/gtksignal.h>
#include <libgnome/gnome-config.h>
#include <libgnome/gnome-util.h>
#include <libgnomevfs/gnome-vfs-utils.h>
static void background_changed_callback (NautilusBackground *background,
NautilusFile *file);
static void background_reset_callback (NautilusBackground *background,
NautilusFile *file);
static void saved_settings_changed_callback (NautilusFile *file,
NautilusBackground *background);
static void nautilus_file_background_receive_root_window_changes (NautilusBackground *background);
static void nautilus_file_update_desktop_pixmaps (NautilusBackground *background);
static void nautilus_file_background_write_desktop_settings (char *color,
char *image,
NautilusBackgroundImagePlacement placement,
gboolean combine);
static gboolean nautilus_file_background_matches_default_settings (
const char* color, const char* default_color,
const char* image, const char* default_image,
NautilusBackgroundImagePlacement placement, NautilusBackgroundImagePlacement default_placement,
gboolean combine, gboolean default_combine);
static void
desktop_background_realized (NautilusIconContainer *icon_container, void *disconnect_signal)
{
NautilusBackground *background;
if ((gboolean) GPOINTER_TO_INT (disconnect_signal)) {
gtk_signal_disconnect_by_func (GTK_OBJECT (icon_container),
GTK_SIGNAL_FUNC (desktop_background_realized),
disconnect_signal);
}
background = nautilus_get_widget_background (GTK_WIDGET (icon_container));
gtk_object_set_data (GTK_OBJECT (background), "icon_container", (gpointer) icon_container);
nautilus_file_update_desktop_pixmaps (background);
}
static const char *default_theme_source = "directory";
static const char *desktop_theme_source = "desktop";
void
static nautilus_background_set_desktop (NautilusIconContainer *icon_container)
{
NautilusBackground *background;
background = nautilus_get_widget_background (GTK_WIDGET (icon_container));
gtk_object_set_data (GTK_OBJECT (background), "theme_source", (gpointer) desktop_theme_source);
if (GTK_LAYOUT (icon_container)->bin_window == NULL) {
gtk_signal_connect (GTK_OBJECT (icon_container), "realize", GTK_SIGNAL_FUNC (desktop_background_realized), GINT_TO_POINTER (TRUE));
} else {
desktop_background_realized (icon_container, GINT_TO_POINTER (FALSE));
}
nautilus_file_background_receive_root_window_changes (background);
}
static gboolean
nautilus_background_is_desktop (NautilusBackground *background)
{
/* == works because we're carful to always use the same string.
*/
return gtk_object_get_data (GTK_OBJECT (background), "theme_source") == desktop_theme_source;
}
static const char *nautilus_file_background_peek_theme_source (NautilusBackground *background)
{
char *theme_source;
theme_source = gtk_object_get_data (GTK_OBJECT (background), "theme_source");
return theme_source != NULL ? theme_source : default_theme_source;
}
static GdkWindow *
nautilus_background_get_desktop_background_window (NautilusBackground *background)
{
return GTK_LAYOUT (gtk_object_get_data (GTK_OBJECT (background), "icon_container"))->bin_window;
}
/* utility routine to handle mapping local image files in themes to a uri */
static char*
theme_image_path_to_uri (char *image_file, const char *theme_name)
{
char *image_path;
char *image_uri;
if (image_file != NULL && !nautilus_istr_has_prefix (image_file, "file://")) {
if (nautilus_str_has_prefix (image_file, "./")) {
image_path = nautilus_theme_get_image_path_from_theme (image_file + 2, theme_name);
} else {
image_path = g_strdup_printf ("%s/%s", NAUTILUS_DATADIR, image_file);
}
g_assert (g_file_exists (image_path));
image_uri = gnome_vfs_get_uri_from_local_path (image_path);
g_free (image_path);
} else {
image_uri = g_strdup (image_file);
}
return image_uri;
}
/* FIXME bugzilla.eazel.com 2190: combine mode (image over gradient) does not work for the
* GNOME desktop. Two things to address are supporting it in the background capplet and
* in whatever code initializes the desktop.
*
* None of our themes currently specify this for the desktop.
*/
static void
nautilus_file_background_get_default_settings_for_theme (const char* theme_name,
const char* theme_source,
char **color,
char **image,
NautilusBackgroundImagePlacement *placement,
gboolean *combine)
{
char *combine_str;
char *image_local_path;
if (placement != NULL) {
*placement = NAUTILUS_BACKGROUND_TILED;
}
if (color != NULL) {
*color = nautilus_theme_get_theme_data_from_theme (theme_source, NAUTILUS_METADATA_KEY_LOCATION_BACKGROUND_COLOR, theme_name);
}
if (image != NULL) {
image_local_path = nautilus_theme_get_theme_data_from_theme (theme_source, NAUTILUS_METADATA_KEY_LOCATION_BACKGROUND_IMAGE, theme_name);
*image = theme_image_path_to_uri (image_local_path, theme_name);
g_free (image_local_path);
}
if (combine != NULL) {
combine_str = nautilus_theme_get_theme_data_from_theme (theme_source, "COMBINE", theme_name);
*combine = combine_str != NULL;
g_free (combine_str);
}
}
static void
nautilus_file_background_get_default_settings (const char* theme_source,
char **color,
char **image,
NautilusBackgroundImagePlacement *placement,
gboolean *combine)
{
char *theme_name;
theme_name = nautilus_theme_get_theme ();
nautilus_file_background_get_default_settings_for_theme
(theme_name, theme_source, color, image, placement, combine);
g_free (theme_name);
}
static gboolean
nautilus_gnome_config_string_match_no_case_with_default (const char *path, const char *test_value, gboolean *was_default)
{
char *value;
gboolean result;
value = gnome_config_get_string_with_default (path, was_default);
result = !nautilus_strcasecmp (value, test_value);
g_free (value);
return result;
}
/* This enum is from gnome-source/control-center/capplets/background-properties/render-background.h */
enum {
WALLPAPER_TILED,
WALLPAPER_CENTERED,
WALLPAPER_SCALED,
WALLPAPER_SCALED_KEEP,
WALLPAPER_EMBOSSED
};
static void
nautilus_file_background_read_desktop_settings (char **color,
char **image,
NautilusBackgroundImagePlacement *placement,
gboolean *combine)
{
int image_alignment;
char* image_local_path;
char* default_image_uri;
gboolean no_alignment_set;
gboolean no_image_set;
NautilusBackgroundImagePlacement default_placement;
char *end_color;
char *start_color;
char *default_color;
gboolean use_gradient;
gboolean is_horizontal;
gboolean no_start_color_set;
gboolean no_end_color_set;
gboolean no_gradient_set;
gboolean no_gradient_orientation_set;
char *theme_name;
char *cur_theme_name;
gboolean no_theme_name_set;
gboolean switch_to_cur_theme_default;
theme_name = gnome_config_get_string_with_default ("/Background/Default/nautilus_theme", &no_theme_name_set);
if (no_theme_name_set) {
nautilus_file_background_get_default_settings
(desktop_theme_source, &default_color, &default_image_uri, &default_placement, combine);
} else {
nautilus_file_background_get_default_settings_for_theme
(theme_name, desktop_theme_source, &default_color, &default_image_uri, &default_placement, combine);
}
/* note - value of combine comes from the theme, not currently setable in gnome_config */
image_local_path = gnome_config_get_string_with_default ("/Background/Default/wallpaper", &no_image_set);
if (no_image_set) {
*image = g_strdup (default_image_uri);
} else if (nautilus_strcasecmp (image_local_path, "none") != 0) {
*image = gnome_vfs_get_uri_from_local_path (image_local_path);
} else {
*image = NULL;
}
g_free(image_local_path);
image_alignment = gnome_config_get_int_with_default ("/Background/Default/wallpaperAlign", &no_alignment_set);
if (no_alignment_set) {
*placement = default_placement;
} else {
switch (image_alignment) {
default:
g_assert_not_reached ();
case WALLPAPER_EMBOSSED:
/* FIXME bugzilla.eazel.com 2193: we don't support embossing.
* Just treat it as centered - ugh.
*/
case WALLPAPER_CENTERED:
*placement = NAUTILUS_BACKGROUND_CENTERED;
break;
case WALLPAPER_TILED:
*placement = NAUTILUS_BACKGROUND_TILED;
break;
case WALLPAPER_SCALED:
*placement = NAUTILUS_BACKGROUND_SCALED;
break;
case WALLPAPER_SCALED_KEEP:
*placement = NAUTILUS_BACKGROUND_SCALED_ASPECT;
break;
}
}
end_color = gnome_config_get_string_with_default ("/Background/Default/color2", &no_end_color_set);
start_color = gnome_config_get_string_with_default ("/Background/Default/color1", &no_start_color_set);
use_gradient = !nautilus_gnome_config_string_match_no_case_with_default ("/Background/Default/simple", "solid", &no_gradient_set);
is_horizontal = !nautilus_gnome_config_string_match_no_case_with_default ("/Background/Default/gradient", "vertical", &no_gradient_orientation_set);
if (no_gradient_set || no_gradient_orientation_set || no_start_color_set) {
*color = g_strdup (default_color);
} else if (use_gradient) {
if (no_end_color_set) {
*color = g_strdup (default_color);
} else {
*color = nautilus_gradient_new (start_color, end_color , is_horizontal);
}
} else {
*color = g_strdup (start_color);
}
g_free(start_color);
g_free(end_color);
/* Since we share our settings with the background-capplet, we can't
* write the default values specially (e.g. by removing them entirely).
*
* The best we can do is check to see if the settings match the default values
* for the theme name that's stored with them. If so, we assume it means use
* the default - i.e. the default from the current theme.
*
* - there must be a theme name stored with the settings
* - if the stored theme name matches the current theme, then
* we don't need to do anything since we're already using
* the current theme's default values.
*
*/
cur_theme_name = nautilus_theme_get_theme ();
switch_to_cur_theme_default = !no_theme_name_set &&
(nautilus_strcmp (theme_name, cur_theme_name) != 0) &&
nautilus_file_background_matches_default_settings
(*color, default_color,
*image, default_image_uri,
*placement, default_placement,
*combine, *combine);
if (switch_to_cur_theme_default) {
g_free (*color);
g_free (*image);
nautilus_file_background_get_default_settings (desktop_theme_source, color, image, placement, combine);
}
if (switch_to_cur_theme_default || no_theme_name_set) {
/* Writing out the actual settings for the current theme so that the
* background capplet will show the right settings.
*/
nautilus_file_background_write_desktop_settings (*color, *image, *placement, *combine);
}
g_free (theme_name);
g_free (cur_theme_name);
g_free(default_color);
g_free(default_image_uri);
}
static void
nautilus_file_background_write_desktop_settings (char *color, char *image, NautilusBackgroundImagePlacement placement, gboolean combine)
{
char *end_color;
char *start_color;
char *image_local_path;
char *theme_name;
int wallpaper_align;
int i;
int wallpaper_count;
char *wallpaper_path_i;
char *wallpaper_config_path_i;
gboolean found_wallpaper;
if (color != NULL) {
start_color = nautilus_gradient_get_start_color_spec (color);
gnome_config_set_string ("/Background/Default/color1", start_color);
g_free (start_color);
/* if color is not a gradient, this ends up writing same as start_color */
end_color = nautilus_gradient_get_end_color_spec (color);
gnome_config_set_string ("/Background/Default/color2", end_color);
g_free (end_color);
gnome_config_set_string ("/Background/Default/simple", nautilus_gradient_is_gradient (color) ? "gradient" : "solid");
gnome_config_set_string ("/Background/Default/gradient", nautilus_gradient_is_horizontal (color) ? "horizontal" : "vertical");
} else {
/* We set it to white here because that's how backgrounds with a NULL color
* are drawn by Nautilus - due to usage of nautilus_gdk_color_parse_with_white_default.
*/
gnome_config_set_string ("/Background/Default/color1", "rgb:FFFF/FFFF/FFFF");
gnome_config_set_string ("/Background/Default/color2", "rgb:FFFF/FFFF/FFFF");
gnome_config_set_string ("/Background/Default/simple", "solid");
gnome_config_set_string ("/Background/Default/gradient", "vertical");
}
if (image != NULL) {
image_local_path = gnome_vfs_get_local_path_from_uri (image);
gnome_config_set_string ("/Background/Default/wallpaper", image_local_path);
switch (placement) {
case NAUTILUS_BACKGROUND_TILED:
wallpaper_align = WALLPAPER_TILED;
break;
case NAUTILUS_BACKGROUND_CENTERED:
wallpaper_align = WALLPAPER_CENTERED;
break;
case NAUTILUS_BACKGROUND_SCALED:
wallpaper_align = WALLPAPER_SCALED;
break;
case NAUTILUS_BACKGROUND_SCALED_ASPECT:
wallpaper_align = WALLPAPER_SCALED_KEEP;
break;
default:
g_assert_not_reached ();
wallpaper_align = WALLPAPER_TILED;
break;
}
gnome_config_set_int ("/Background/Default/wallpaperAlign", wallpaper_align);
wallpaper_count = gnome_config_get_int ("/Background/Default/wallpapers=0");
found_wallpaper = FALSE;
for (i = 1; i <= wallpaper_count && !found_wallpaper; ++i) {
wallpaper_config_path_i = g_strdup_printf ("/Background/Default/wallpaper%d", i);
wallpaper_path_i = gnome_config_get_string (wallpaper_config_path_i);
g_free (wallpaper_config_path_i);
if (nautilus_strcmp (wallpaper_path_i, image_local_path) == 0) {
found_wallpaper = TRUE;
}
g_free (wallpaper_path_i);
}
if (!found_wallpaper) {
gnome_config_set_int ("/Background/Default/wallpapers", wallpaper_count + 1);
gnome_config_set_string ("/Background/Default/wallpapers_dir", image_local_path);
wallpaper_config_path_i = g_strdup_printf ("/Background/Default/wallpaper%d", wallpaper_count + 1);
gnome_config_set_string (wallpaper_config_path_i, image_local_path);
g_free (wallpaper_config_path_i);
}
g_free (image_local_path);
} else {
gnome_config_set_string ("/Background/Default/wallpaper", "none");
}
theme_name = nautilus_theme_get_theme ();
gnome_config_set_string ("/Background/Default/nautilus_theme", theme_name);
g_free (theme_name);
gnome_config_sync ();
}
static void
nautilus_file_background_write_desktop_default_settings ()
{
char *color;
char *image;
gboolean combine;
NautilusBackgroundImagePlacement placement;
nautilus_file_background_get_default_settings (desktop_theme_source, &color, &image, &placement, &combine);
nautilus_file_background_write_desktop_settings (color, image, placement, combine);
}
static int
call_settings_changed (NautilusBackground *background)
{
NautilusFile *file;
file = gtk_object_get_data (GTK_OBJECT (background), "nautilus_background_file");
if (file) {
saved_settings_changed_callback (file, background);
}
return FALSE;
}
/* We don't want to respond to our own changes to the root pixmap.
* Since there's no way to determine the origin of the x-event (or mark it)
* we use this variable determine if we think the next PropertyNotify is
* due to us.
*/
static int set_root_pixmap_count = 0;
static GdkFilterReturn
nautilus_file_background_event_filter (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data)
{
XEvent *xevent;
NautilusBackground *background;
xevent = (XEvent *) gdk_xevent;
if (xevent->type == PropertyNotify && xevent->xproperty.atom == gdk_atom_intern("ESETROOT_PMAP_ID", TRUE)) {
/* If we caused it, ignore it.
*/
if (set_root_pixmap_count > 0) {
--set_root_pixmap_count;
return GDK_FILTER_CONTINUE;
}
background = NAUTILUS_BACKGROUND (data);
/* FIXME bugzilla.eazel.com 2220:
* We'd like to call saved_settings_changed_callback right here, directly.
* However, the current version of the property-background capplet saves
* the new setting in gnome_config AFTER setting the root window's property -
* i.e. after we get this event. How long afterwards is not knowable - we
* guess half a second. Fixing this requires changing the capplet.
*/
gtk_timeout_add (500, (GtkFunction) (call_settings_changed), background);
}
return GDK_FILTER_CONTINUE;
}
static void
desktop_background_destroyed_callback (NautilusBackground *background, void *georgeWBush)
{
gdk_window_remove_filter (GDK_ROOT_PARENT(), nautilus_file_background_event_filter, background);
}
static void
nautilus_file_background_receive_root_window_changes (NautilusBackground *background)
{
XWindowAttributes attribs = { 0 };
/* set up a filter on the root window to get notified about property changes */
gdk_window_add_filter (GDK_ROOT_PARENT(), nautilus_file_background_event_filter, background);
gdk_error_trap_push ();
/* select events, we need to trap the kde status thingies anyway */
XGetWindowAttributes (GDK_DISPLAY (), GDK_ROOT_WINDOW (), &attribs);
XSelectInput (GDK_DISPLAY (), GDK_ROOT_WINDOW (), attribs.your_event_mask | PropertyChangeMask);
gdk_flush ();
gdk_error_trap_pop ();
gtk_signal_connect (GTK_OBJECT (background),
"destroy",
GTK_SIGNAL_FUNC (desktop_background_destroyed_callback),
NULL);
}
/* Create a persistant pixmap. We create a separate display
* and set the closedown mode on it to RetainPermanent
* (copied from gnome-source/control-panels/capplets/background-properties/render-background.c)
*/
static GdkPixmap *
make_root_pixmap (gint width, gint height)
{
Display *display;
Pixmap result;
gdk_flush ();
display = XOpenDisplay (gdk_display_name);
XSetCloseDownMode (display, RetainPermanent);
result = XCreatePixmap (display,
DefaultRootWindow (display),
width, height,
DefaultDepthOfScreen (DefaultScreenOfDisplay (GDK_DISPLAY())));
XCloseDisplay (display);
return gdk_pixmap_foreign_new (result);
}
/* (copied from gnome-source/control-panels/capplets/background-properties/render-background.c)
*/
static void
dispose_root_pixmap (GdkPixmap *pixmap)
{
/* Unrefing a foreign pixmap causes it to be destroyed - so we include
* this bad hack, that will work for GTK+-1.2 until the problem
* is fixed in the next release
*/
GdkWindowPrivate *private = (GdkWindowPrivate *)pixmap;
gdk_xid_table_remove (private->xwindow);
g_dataset_destroy (private);
g_free (private);
}
/* 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
* (copied from gnome-source/control-panels/capplets/background-properties/render-background.c)
*/
static void
set_root_pixmap (GdkPixmap *pixmap)
{
int result;
gint format;
gulong nitems;
gulong bytes_after;
guchar *data_esetroot;
Pixmap pixmap_id;
GdkAtom type;
data_esetroot = NULL;
XGrabServer (GDK_DISPLAY());
result = XGetWindowProperty (GDK_DISPLAY(), GDK_ROOT_WINDOW(),
gdk_atom_intern("ESETROOT_PMAP_ID", FALSE),
0L, 1L, False, XA_PIXMAP,
&type, &format, &nitems, &bytes_after,
&data_esetroot);
if (result == Success && type == XA_PIXMAP && format == 32 && nitems == 1) {
XKillClient(GDK_DISPLAY(), *(Pixmap*)data_esetroot);
}
if (data_esetroot != NULL) {
XFree (data_esetroot);
}
++set_root_pixmap_count;
pixmap_id = GDK_WINDOW_XWINDOW (pixmap);
XChangeProperty (GDK_DISPLAY(), GDK_ROOT_WINDOW(),
gdk_atom_intern("ESETROOT_PMAP_ID", FALSE), XA_PIXMAP,
32, PropModeReplace,
(guchar *) &pixmap_id, 1);
XChangeProperty (GDK_DISPLAY(), GDK_ROOT_WINDOW(),
gdk_atom_intern("_XROOTPMAP_ID", FALSE), XA_PIXMAP,
32, PropModeReplace,
(guchar *) &pixmap_id, 1);
XSetWindowBackgroundPixmap (GDK_DISPLAY(), GDK_ROOT_WINDOW(), pixmap_id);
XClearWindow (GDK_DISPLAY (), GDK_ROOT_WINDOW ());
XUngrabServer (GDK_DISPLAY());
XFlush(GDK_DISPLAY());
}
static void
image_loading_done_callback (NautilusBackground *background, gboolean successful_load, void *disconnect_signal)
{
int width;
int height;
GdkGC *gc;
GdkPixmap *pixmap;
if ((gboolean) GPOINTER_TO_INT (disconnect_signal)) {
gtk_signal_disconnect_by_func (GTK_OBJECT (background),
GTK_SIGNAL_FUNC (image_loading_done_callback),
disconnect_signal);
}
width = gdk_screen_width ();
height = gdk_screen_height ();
pixmap = make_root_pixmap (width, height);
gc = gdk_gc_new (pixmap);
nautilus_background_draw_to_drawable (background, pixmap, gc, 0, 0, width, height, width, height);
gdk_gc_unref (gc);
set_root_pixmap (pixmap);
gdk_window_set_back_pixmap (nautilus_background_get_desktop_background_window (background), pixmap, FALSE);
dispose_root_pixmap (pixmap);
}
static void
nautilus_file_update_desktop_pixmaps (NautilusBackground *background)
{
if (nautilus_background_is_loaded (background)) {
image_loading_done_callback (background, TRUE, GINT_TO_POINTER (FALSE));
} else {
gtk_signal_connect (GTK_OBJECT (background),
"image_loading_done",
GTK_SIGNAL_FUNC (image_loading_done_callback),
GINT_TO_POINTER (TRUE));
}
}
static gboolean
nautilus_file_background_matches_default_settings (
const char* color, const char* default_color,
const char* image, const char* default_image,
NautilusBackgroundImagePlacement placement, NautilusBackgroundImagePlacement default_placement,
gboolean combine, gboolean default_combine)
{
gboolean match_color;
gboolean match_image;
/* A NULL default color or image is not considered when determining a match.
*/
match_color = (default_color == NULL) || nautilus_strcmp (color, default_color) == 0;
match_image = (default_image == NULL) || ((nautilus_strcmp (image, default_image) == 0) &&
(placement == default_placement) &&
(combine == default_combine));
return match_color && match_image;
}
/* return true if the background is not in the default state */
gboolean
nautilus_file_background_is_set (NautilusBackground *background)
{
char *color;
char *image;
char *default_color;
char *default_image;
gboolean matches;
gboolean combine;
gboolean default_combine;
NautilusBackgroundImagePlacement placement;
NautilusBackgroundImagePlacement default_placement;
color = nautilus_background_get_color (background);
image = nautilus_background_get_image_uri (background);
combine = nautilus_background_get_combine_mode (background);
placement = nautilus_background_get_image_placement (background);
nautilus_file_background_get_default_settings (
nautilus_file_background_peek_theme_source (background),
&default_color, &default_image, &default_placement, &default_combine);
matches = !nautilus_file_background_matches_default_settings (color, default_color,
image, default_image,
placement, default_placement,
combine, default_combine);
g_free (color);
g_free (image);
g_free (default_color);
g_free (default_image);
return !matches;
}
/* handle the background changed signal */
static void
background_changed_callback (NautilusBackground *background,
NautilusFile *file)
{
char *color;
char *image;
g_assert (NAUTILUS_IS_BACKGROUND (background));
g_assert (NAUTILUS_IS_FILE (file));
g_assert (gtk_object_get_data (GTK_OBJECT (background), "nautilus_background_file") == file);
color = nautilus_background_get_color (background);
image = nautilus_background_get_image_uri (background);
if (nautilus_background_is_desktop (background)) {
nautilus_file_background_write_desktop_settings (color, image, nautilus_background_get_image_placement (background), nautilus_background_get_combine_mode (background));
} else {
/* Block the other handler while we are writing metadata so it doesn't
* try to change the background.
*/
gtk_signal_handler_block_by_func (GTK_OBJECT (file),
saved_settings_changed_callback,
background);
nautilus_file_set_metadata (file,
NAUTILUS_METADATA_KEY_LOCATION_BACKGROUND_COLOR,
NULL,
color);
nautilus_file_set_metadata (file,
NAUTILUS_METADATA_KEY_LOCATION_BACKGROUND_IMAGE,
NULL,
image);
/* Unblock the handler. */
gtk_signal_handler_unblock_by_func (GTK_OBJECT (file),
saved_settings_changed_callback,
background);
}
g_free (color);
g_free (image);
if (nautilus_background_is_desktop (background)) {
nautilus_file_update_desktop_pixmaps (background);
}
}
/* handle the file changed signal */
static void
saved_settings_changed_callback (NautilusFile *file,
NautilusBackground *background)
{
char *color;
char *image;
gboolean combine;
NautilusBackgroundImagePlacement placement;
g_assert (NAUTILUS_IS_FILE (file));
g_assert (NAUTILUS_IS_BACKGROUND (background));
g_assert (gtk_object_get_data (GTK_OBJECT (background), "nautilus_background_file")
== file);
if (nautilus_background_is_desktop (background)) {
nautilus_file_background_read_desktop_settings (&color, &image, &placement, &combine);
} else {
color = nautilus_file_get_metadata (file,
NAUTILUS_METADATA_KEY_LOCATION_BACKGROUND_COLOR,
NULL);
image = nautilus_file_get_metadata (file,
NAUTILUS_METADATA_KEY_LOCATION_BACKGROUND_IMAGE,
NULL);
placement = NAUTILUS_BACKGROUND_TILED; /* non-tiled only avail for desktop, at least for now */
combine = FALSE; /* only from theme, at least for now */
/* if there's none, read the default from the theme */
if (color == NULL && image == NULL) {
nautilus_file_background_get_default_settings
(nautilus_file_background_peek_theme_source (background),
&color, &image, &placement, &combine);
}
}
/* Block the other handler while we are responding to changes
* in the metadata so it doesn't try to change the metadata.
*/
gtk_signal_handler_block_by_func (GTK_OBJECT (background),
background_changed_callback,
file);
nautilus_background_set_color (background, color);
nautilus_background_set_image_uri (background, image);
nautilus_background_set_combine_mode (background, combine);
nautilus_background_set_image_placement (background, placement);
/* Unblock the handler. */
gtk_signal_handler_unblock_by_func (GTK_OBJECT (background),
background_changed_callback,
file);
g_free (color);
g_free (image);
}
/* handle the theme changing */
static void
nautilus_file_background_theme_changed (gpointer user_data)
{
NautilusFile *file;
NautilusBackground *background;
background = NAUTILUS_BACKGROUND (user_data);
file = gtk_object_get_data (GTK_OBJECT (background), "nautilus_background_file");
if (file) {
saved_settings_changed_callback (file, background);
}
}
/* handle the background reset signal by setting values from the current theme */
static void
background_reset_callback (NautilusBackground *background,
NautilusFile *file)
{
if (nautilus_background_is_desktop (background)) {
nautilus_file_background_write_desktop_default_settings ();
} else {
/* Block the other handler while we are writing metadata so it doesn't
* try to change the background.
*/
gtk_signal_handler_block_by_func (GTK_OBJECT (file),
saved_settings_changed_callback,
background);
/* reset the metadata */
nautilus_file_set_metadata (file,
NAUTILUS_METADATA_KEY_LOCATION_BACKGROUND_COLOR,
NULL,
NULL);
nautilus_file_set_metadata (file,
NAUTILUS_METADATA_KEY_LOCATION_BACKGROUND_IMAGE,
NULL,
NULL);
/* Unblock the handler. */
gtk_signal_handler_unblock_by_func (GTK_OBJECT (file),
saved_settings_changed_callback,
background);
}
saved_settings_changed_callback (file, background);
if (nautilus_background_is_desktop (background)) {
nautilus_file_update_desktop_pixmaps (background);
}
}
/* handle the background destroyed signal */
static void
background_destroyed_callback (NautilusBackground *background,
NautilusFile *file)
{
gtk_signal_disconnect_by_func (GTK_OBJECT (file),
GTK_SIGNAL_FUNC (saved_settings_changed_callback),
background);
nautilus_file_monitor_remove (file, background);
nautilus_preferences_remove_callback (NAUTILUS_PREFERENCES_THEME,
nautilus_file_background_theme_changed,
background);
}
/* key routine that hooks up a background and location */
void
nautilus_connect_background_to_file_metadata (GtkWidget *widget,
NautilusFile *file)
{
NautilusBackground *background;
gpointer old_file;
GList *attributes;
/* Get at the background object we'll be connecting. */
background = nautilus_get_widget_background (widget);
/* Check if it is already connected. */
old_file = gtk_object_get_data (GTK_OBJECT (background), "nautilus_background_file");
if (old_file == file) {
return;
}
/* Disconnect old signal handlers. */
if (old_file != NULL) {
g_assert (NAUTILUS_IS_FILE (old_file));
gtk_signal_disconnect_by_func (GTK_OBJECT (background),
GTK_SIGNAL_FUNC (background_changed_callback),
old_file);
gtk_signal_disconnect_by_func (GTK_OBJECT (background),
GTK_SIGNAL_FUNC (background_destroyed_callback),
old_file);
gtk_signal_disconnect_by_func (GTK_OBJECT (background),
GTK_SIGNAL_FUNC (background_reset_callback),
old_file);
gtk_signal_disconnect_by_func (GTK_OBJECT (old_file),
GTK_SIGNAL_FUNC (saved_settings_changed_callback),
background);
nautilus_file_monitor_remove (old_file, background);
nautilus_preferences_remove_callback (NAUTILUS_PREFERENCES_THEME,
nautilus_file_background_theme_changed,
background);
}
/* Attach the new directory. */
nautilus_file_ref (file);
gtk_object_set_data_full (GTK_OBJECT (background),
"nautilus_background_file",
file,
(GtkDestroyNotify) nautilus_file_unref);
/* Connect new signal handlers. */
if (file != NULL) {
gtk_signal_connect (GTK_OBJECT (background),
"settings_changed",
GTK_SIGNAL_FUNC (background_changed_callback),
file);
gtk_signal_connect (GTK_OBJECT (background),
"destroy",
GTK_SIGNAL_FUNC (background_destroyed_callback),
file);
gtk_signal_connect (GTK_OBJECT (background),
"reset",
GTK_SIGNAL_FUNC (background_reset_callback),
file);
gtk_signal_connect (GTK_OBJECT (file),
"changed",
GTK_SIGNAL_FUNC (saved_settings_changed_callback),
background);
/* arrange to receive file metadata */
attributes = g_list_append (NULL, NAUTILUS_FILE_ATTRIBUTE_METADATA);
nautilus_file_monitor_add (file,
background,
attributes);
g_list_free (attributes);
/* arrange for notification when the theme changes */
nautilus_preferences_add_callback (NAUTILUS_PREFERENCES_THEME,
nautilus_file_background_theme_changed, background);
}
/* Update the background based on the file metadata. */
saved_settings_changed_callback (file, background);
}
void
nautilus_connect_desktop_background_to_file_metadata (NautilusIconContainer *icon_container,
NautilusFile *file)
{
nautilus_background_set_desktop (icon_container);
/* Strictly speaking, we don't need to know about metadata changes, since
* the desktop setting aren't stored there. But, hooking up to metadata
* changes is actually a small part of what this fn does, and we do need
* the other stuff (hooked up to background & theme changes). Being notified
* of metadata changes on the file is a waste, but won't hurt, so I don't
* think it's worth refactoring the fn at this point.
*/
nautilus_connect_background_to_file_metadata (GTK_WIDGET (icon_container), file);
}
void
nautilus_connect_background_to_file_metadata_by_uri (GtkWidget *widget,
const char *uri)
{
NautilusFile *file;
file = nautilus_file_get (uri);
nautilus_connect_background_to_file_metadata (widget, file);
nautilus_file_unref (file);
}