summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog23
-rw-r--r--libnautilus-extensions/nautilus-background.c82
-rw-r--r--libnautilus-extensions/nautilus-background.h7
-rw-r--r--libnautilus-extensions/nautilus-directory-background.c150
-rw-r--r--libnautilus-private/nautilus-background.c82
-rw-r--r--libnautilus-private/nautilus-background.h7
-rw-r--r--libnautilus-private/nautilus-directory-background.c150
7 files changed, 445 insertions, 56 deletions
diff --git a/ChangeLog b/ChangeLog
index 1f96425f6..501210616 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,26 @@
+2000-08-15 Michael Engber <engber@eazel.com>
+
+ Third cut at syncing our desktop background with GNOME's (bug 1047)
+ Now we update the GNOME desktop (root window) when we make changes.
+ Still need to handle nautilus getting notified when the capplet makes
+ changes.
+
+ * libnautilus-extensions/nautilus-background.c:
+ (nautilus_background_initialize_class),
+ (nautilus_background_set_color_no_signal),
+ (nautilus_background_set_color), (load_image_callback),
+ (nautilus_background_set_image_uri_no_signal),
+ (nautilus_background_set_image_uri),
+ (nautilus_background_is_loaded), (nautilus_background_real_reset),
+ (nautilus_background_receive_dropped_color):
+ * libnautilus-extensions/nautilus-background.h:
+ * libnautilus-extensions/nautilus-directory-background.c:
+ (nautilus_directory_background_write_desktop_settings),
+ (nautilus_directory_background_write_desktop_default_settings),
+ (make_root_pixmap), (dispose_root_pixmap), (set_root_pixmap),
+ (image_loaded_callback), (nautilus_directory_update_root_window),
+ (background_changed_callback), (background_reset_callback):
+
2000-08-15 Darin Adler <darin@eazel.com>
* libnautilus-extensions/nautilus-search-uri.c:
diff --git a/libnautilus-extensions/nautilus-background.c b/libnautilus-extensions/nautilus-background.c
index e4a3a2a92..108f86f56 100644
--- a/libnautilus-extensions/nautilus-background.c
+++ b/libnautilus-extensions/nautilus-background.c
@@ -64,6 +64,7 @@ NAUTILUS_DEFINE_CLASS_BOILERPLATE (NautilusBackground, nautilus_background, GTK_
enum {
APPEARANCE_CHANGED,
SETTINGS_CHANGED,
+ IMAGE_LOADED,
RESET,
LAST_SIGNAL
};
@@ -108,6 +109,15 @@ nautilus_background_initialize_class (gpointer klass)
gtk_marshal_NONE__NONE,
GTK_TYPE_NONE,
0);
+ signals[IMAGE_LOADED] =
+ gtk_signal_new ("image_loaded",
+ GTK_RUN_LAST | GTK_RUN_NO_RECURSE,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (NautilusBackgroundClass,
+ image_loaded),
+ gtk_marshal_NONE__NONE,
+ GTK_TYPE_NONE,
+ 0);
signals[RESET] =
gtk_signal_new ("reset",
GTK_RUN_LAST | GTK_RUN_NO_RECURSE,
@@ -532,25 +542,32 @@ nautilus_background_get_image_uri (NautilusBackground *background)
return g_strdup (background->details->image_uri);
}
-void
-nautilus_background_set_color (NautilusBackground *background,
+static gboolean
+nautilus_background_set_color_no_signal (NautilusBackground *background,
const char *color)
{
- g_return_if_fail (NAUTILUS_IS_BACKGROUND (background));
+ g_return_val_if_fail (NAUTILUS_IS_BACKGROUND (background), FALSE);
if (nautilus_strcmp (background->details->color, color) == 0) {
- return;
+ return FALSE;
}
g_free (background->details->color);
background->details->color = g_strdup (color);
+ return TRUE;
+}
- gtk_signal_emit (GTK_OBJECT (background),
- signals[SETTINGS_CHANGED]);
- gtk_signal_emit (GTK_OBJECT (background),
- signals[APPEARANCE_CHANGED]);
+void
+nautilus_background_set_color (NautilusBackground *background,
+ const char *color)
+{
+ if (nautilus_background_set_color_no_signal (background, color)) {
+ gtk_signal_emit (GTK_OBJECT (background), signals[SETTINGS_CHANGED]);
+ gtk_signal_emit (GTK_OBJECT (background), signals[APPEARANCE_CHANGED]);
+ }
}
+
static void
load_image_callback (GnomeVFSResult error,
GdkPixbuf *pixbuf,
@@ -575,6 +592,8 @@ load_image_callback (GnomeVFSResult error,
gtk_signal_emit (GTK_OBJECT (background),
signals[APPEARANCE_CHANGED]);
+ gtk_signal_emit (GTK_OBJECT (background),
+ signals[IMAGE_LOADED]);
}
static void
@@ -602,14 +621,14 @@ nautilus_background_receive_dropped_background_image (NautilusBackground *backgr
}
}
-void
-nautilus_background_set_image_uri (NautilusBackground *background,
+static gboolean
+nautilus_background_set_image_uri_no_signal (NautilusBackground *background,
const char *image_uri)
{
- g_return_if_fail (NAUTILUS_IS_BACKGROUND (background));
+ g_return_val_if_fail (NAUTILUS_IS_BACKGROUND (background), FALSE);
if (nautilus_strcmp (background->details->image_uri, image_uri) == 0) {
- return;
+ return FALSE;
}
nautilus_cancel_gdk_pixbuf_load (background->details->load_image_handle);
@@ -624,10 +643,17 @@ nautilus_background_set_image_uri (NautilusBackground *background,
background->details->image_uri = g_strdup (image_uri);
start_loading_image (background);
- gtk_signal_emit (GTK_OBJECT (background),
- signals[SETTINGS_CHANGED]);
- gtk_signal_emit (GTK_OBJECT (background),
- signals[APPEARANCE_CHANGED]);
+ return TRUE;
+}
+
+void
+nautilus_background_set_image_uri (NautilusBackground *background,
+ const char *image_uri)
+{
+ if (nautilus_background_set_image_uri_no_signal (background, image_uri)) {
+ gtk_signal_emit (GTK_OBJECT (background), signals[SETTINGS_CHANGED]);
+ gtk_signal_emit (GTK_OBJECT (background), signals[APPEARANCE_CHANGED]);
+ }
}
static GtkStyleClass *
@@ -774,6 +800,16 @@ nautilus_background_is_set (NautilusBackground *background)
background->details->image_uri != NULL;
}
+/* Returns false if the image is still loading, true
+ * if it's done loading or there is no image.
+ */
+gboolean
+nautilus_background_is_loaded (NautilusBackground *background)
+{
+ return background->details->image_uri == NULL ||
+ background->details->image != NULL;
+}
+
/**
* nautilus_background_reset:
*
@@ -790,8 +826,10 @@ nautilus_background_reset (NautilusBackground *background)
static void
nautilus_background_real_reset (NautilusBackground *background)
{
- nautilus_background_set_color (background, NULL);
- nautilus_background_set_image_uri (background, NULL);
+ nautilus_background_set_color_no_signal (background, NULL);
+ nautilus_background_set_image_uri_no_signal (background, NULL);
+ gtk_signal_emit (GTK_OBJECT (background), signals[SETTINGS_CHANGED]);
+ gtk_signal_emit (GTK_OBJECT (background), signals[APPEARANCE_CHANGED]);
}
static void
@@ -974,9 +1012,11 @@ nautilus_background_receive_dropped_color (NautilusBackground *background,
g_free (color_spec);
- nautilus_background_set_color (background, new_gradient_spec);
- nautilus_background_set_image_uri (background, NULL);
-
+ nautilus_background_set_color_no_signal (background, new_gradient_spec);
+ nautilus_background_set_image_uri_no_signal (background, NULL);
+ gtk_signal_emit (GTK_OBJECT (background), signals[SETTINGS_CHANGED]);
+ gtk_signal_emit (GTK_OBJECT (background), signals[APPEARANCE_CHANGED]);
+
g_free (new_gradient_spec);
}
diff --git a/libnautilus-extensions/nautilus-background.h b/libnautilus-extensions/nautilus-background.h
index 843ebb164..1e653601d 100644
--- a/libnautilus-extensions/nautilus-background.h
+++ b/libnautilus-extensions/nautilus-background.h
@@ -80,12 +80,13 @@ void nautilus_background_set_image_placement (Nautil
/* Calls to interrogate the current state of a background. */
char * nautilus_background_get_color (NautilusBackground *background);
-char * nautilus_background_get_image_uri (NautilusBackground *background);
+char * nautilus_background_get_image_uri (NautilusBackground *background);
gboolean nautilus_background_get_combine_mode (NautilusBackground *background);
nautilus_background_image_placement
nautilus_background_get_image_placement (NautilusBackground *background);
gboolean nautilus_background_is_dark (NautilusBackground *background);
gboolean nautilus_background_is_set (NautilusBackground *background);
+gboolean nautilus_background_is_loaded (NautilusBackground *background);
/* Explicitly fills a rectangle with a background. */
void nautilus_background_draw (NautilusBackground *background,
@@ -141,6 +142,10 @@ struct NautilusBackgroundClass
*/
void (* appearance_changed) (NautilusBackground *);
+ /* This signal is emitted whenever an image is loaded.
+ */
+ void (* image_loaded) (NautilusBackground *);
+
/* This signal is emitted when the background is reset by receiving
the reset property from a drag */
diff --git a/libnautilus-extensions/nautilus-directory-background.c b/libnautilus-extensions/nautilus-directory-background.c
index d5812cfbc..9f08dbbf7 100644
--- a/libnautilus-extensions/nautilus-directory-background.c
+++ b/libnautilus-extensions/nautilus-directory-background.c
@@ -36,13 +36,16 @@
#include "nautilus-theme.h"
#include "libnautilus-extensions/nautilus-gdk-extensions.h"
+#include <gdk/gdkx.h>
+#include <X11/Xatom.h>
+
static void background_changed_callback (NautilusBackground *background,
NautilusDirectory *directory);
static void directory_changed_callback (NautilusDirectory *directory,
NautilusBackground *background);
static void background_reset_callback (NautilusBackground *background,
NautilusDirectory *directory);
-
+
void
static nautilus_directory_background_set_desktop (NautilusBackground *background)
{
@@ -257,10 +260,6 @@ nautilus_directory_background_write_desktop_settings (char *color, char *image,
}
gnome_config_sync ();
-
- /* FIXME
- * Try to trick GNOME into re-reading the settings.
- */
}
static void
@@ -272,7 +271,138 @@ nautilus_directory_background_write_desktop_default_settings ()
nautilus_background_image_placement placement;
nautilus_directory_background_get_default_settings (TRUE, &color, &image, &placement, &combine);
nautilus_directory_background_write_desktop_settings (color, image, placement, combine);
-}
+}
+
+/* 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)
+{
+ Pixmap result;
+
+ gdk_flush ();
+
+ XSetCloseDownMode (gdk_display, RetainPermanent);
+
+ result = XCreatePixmap (gdk_display,
+ DefaultRootWindow (gdk_display),
+ width, height,
+ DefaultDepthOfScreen (DefaultScreenOfDisplay (GDK_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)
+{
+ GdkAtom type;
+ gulong nitems, bytes_after;
+ gint format;
+ guchar *data_esetroot;
+ Pixmap pixmap_id = GDK_WINDOW_XWINDOW (pixmap);
+
+ XGrabServer (GDK_DISPLAY());
+
+ 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 (type == XA_PIXMAP) {
+ if (format == 32 && nitems == 4)
+ XKillClient(GDK_DISPLAY(), *((Pixmap*)data_esetroot));
+
+ XFree (data_esetroot);
+ }
+
+ 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_loaded_callback (NautilusBackground *background, void *calledDirectly)
+{
+ GdkGC *gc;
+ GdkPixmap *bg_pixmap;
+ GdkRectangle screen_rectangle;
+
+ g_assert (NAUTILUS_IS_BACKGROUND (background));
+
+ if (!(gboolean) calledDirectly) {
+ gtk_signal_disconnect_by_func (GTK_OBJECT (background),
+ GTK_SIGNAL_FUNC (image_loaded_callback),
+ calledDirectly);
+ }
+
+ screen_rectangle.x = 0;
+ screen_rectangle.y = 0;
+ screen_rectangle.width = gdk_screen_width ();
+ screen_rectangle.height = gdk_screen_height ();
+
+ bg_pixmap = make_root_pixmap (screen_rectangle.width, screen_rectangle.height);
+ gc = gdk_gc_new (bg_pixmap);
+
+ nautilus_background_draw (background, bg_pixmap, gc, &screen_rectangle, 0, 0);
+
+ set_root_pixmap (bg_pixmap);
+
+ dispose_root_pixmap (bg_pixmap);
+ gdk_gc_unref (gc);
+}
+
+static void
+nautilus_directory_update_root_window (NautilusBackground *background)
+{
+ if (nautilus_background_is_loaded (background)) {
+ image_loaded_callback (background, (void *) TRUE);
+ } else {
+ gtk_signal_connect (GTK_OBJECT (background),
+ "image_loaded",
+ GTK_SIGNAL_FUNC (image_loaded_callback),
+ (void *) FALSE);
+ }
+}
/* return true if the background is not in the default state */
gboolean
@@ -353,6 +483,10 @@ background_changed_callback (NautilusBackground *background,
g_free (color);
g_free (image);
+
+ if (nautilus_directory_background_is_desktop (background)) {
+ nautilus_directory_update_root_window (background);
+ }
}
/* handle the directory changed signal */
@@ -461,6 +595,10 @@ background_reset_callback (NautilusBackground *background,
* It will set color and image_uri to NULL.
*/
gtk_signal_emit_stop_by_name (GTK_OBJECT (background), "reset");
+
+ if (nautilus_directory_background_is_desktop (background)) {
+ nautilus_directory_update_root_window (background);
+ }
}
/* handle the background destroyed signal */
diff --git a/libnautilus-private/nautilus-background.c b/libnautilus-private/nautilus-background.c
index e4a3a2a92..108f86f56 100644
--- a/libnautilus-private/nautilus-background.c
+++ b/libnautilus-private/nautilus-background.c
@@ -64,6 +64,7 @@ NAUTILUS_DEFINE_CLASS_BOILERPLATE (NautilusBackground, nautilus_background, GTK_
enum {
APPEARANCE_CHANGED,
SETTINGS_CHANGED,
+ IMAGE_LOADED,
RESET,
LAST_SIGNAL
};
@@ -108,6 +109,15 @@ nautilus_background_initialize_class (gpointer klass)
gtk_marshal_NONE__NONE,
GTK_TYPE_NONE,
0);
+ signals[IMAGE_LOADED] =
+ gtk_signal_new ("image_loaded",
+ GTK_RUN_LAST | GTK_RUN_NO_RECURSE,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (NautilusBackgroundClass,
+ image_loaded),
+ gtk_marshal_NONE__NONE,
+ GTK_TYPE_NONE,
+ 0);
signals[RESET] =
gtk_signal_new ("reset",
GTK_RUN_LAST | GTK_RUN_NO_RECURSE,
@@ -532,25 +542,32 @@ nautilus_background_get_image_uri (NautilusBackground *background)
return g_strdup (background->details->image_uri);
}
-void
-nautilus_background_set_color (NautilusBackground *background,
+static gboolean
+nautilus_background_set_color_no_signal (NautilusBackground *background,
const char *color)
{
- g_return_if_fail (NAUTILUS_IS_BACKGROUND (background));
+ g_return_val_if_fail (NAUTILUS_IS_BACKGROUND (background), FALSE);
if (nautilus_strcmp (background->details->color, color) == 0) {
- return;
+ return FALSE;
}
g_free (background->details->color);
background->details->color = g_strdup (color);
+ return TRUE;
+}
- gtk_signal_emit (GTK_OBJECT (background),
- signals[SETTINGS_CHANGED]);
- gtk_signal_emit (GTK_OBJECT (background),
- signals[APPEARANCE_CHANGED]);
+void
+nautilus_background_set_color (NautilusBackground *background,
+ const char *color)
+{
+ if (nautilus_background_set_color_no_signal (background, color)) {
+ gtk_signal_emit (GTK_OBJECT (background), signals[SETTINGS_CHANGED]);
+ gtk_signal_emit (GTK_OBJECT (background), signals[APPEARANCE_CHANGED]);
+ }
}
+
static void
load_image_callback (GnomeVFSResult error,
GdkPixbuf *pixbuf,
@@ -575,6 +592,8 @@ load_image_callback (GnomeVFSResult error,
gtk_signal_emit (GTK_OBJECT (background),
signals[APPEARANCE_CHANGED]);
+ gtk_signal_emit (GTK_OBJECT (background),
+ signals[IMAGE_LOADED]);
}
static void
@@ -602,14 +621,14 @@ nautilus_background_receive_dropped_background_image (NautilusBackground *backgr
}
}
-void
-nautilus_background_set_image_uri (NautilusBackground *background,
+static gboolean
+nautilus_background_set_image_uri_no_signal (NautilusBackground *background,
const char *image_uri)
{
- g_return_if_fail (NAUTILUS_IS_BACKGROUND (background));
+ g_return_val_if_fail (NAUTILUS_IS_BACKGROUND (background), FALSE);
if (nautilus_strcmp (background->details->image_uri, image_uri) == 0) {
- return;
+ return FALSE;
}
nautilus_cancel_gdk_pixbuf_load (background->details->load_image_handle);
@@ -624,10 +643,17 @@ nautilus_background_set_image_uri (NautilusBackground *background,
background->details->image_uri = g_strdup (image_uri);
start_loading_image (background);
- gtk_signal_emit (GTK_OBJECT (background),
- signals[SETTINGS_CHANGED]);
- gtk_signal_emit (GTK_OBJECT (background),
- signals[APPEARANCE_CHANGED]);
+ return TRUE;
+}
+
+void
+nautilus_background_set_image_uri (NautilusBackground *background,
+ const char *image_uri)
+{
+ if (nautilus_background_set_image_uri_no_signal (background, image_uri)) {
+ gtk_signal_emit (GTK_OBJECT (background), signals[SETTINGS_CHANGED]);
+ gtk_signal_emit (GTK_OBJECT (background), signals[APPEARANCE_CHANGED]);
+ }
}
static GtkStyleClass *
@@ -774,6 +800,16 @@ nautilus_background_is_set (NautilusBackground *background)
background->details->image_uri != NULL;
}
+/* Returns false if the image is still loading, true
+ * if it's done loading or there is no image.
+ */
+gboolean
+nautilus_background_is_loaded (NautilusBackground *background)
+{
+ return background->details->image_uri == NULL ||
+ background->details->image != NULL;
+}
+
/**
* nautilus_background_reset:
*
@@ -790,8 +826,10 @@ nautilus_background_reset (NautilusBackground *background)
static void
nautilus_background_real_reset (NautilusBackground *background)
{
- nautilus_background_set_color (background, NULL);
- nautilus_background_set_image_uri (background, NULL);
+ nautilus_background_set_color_no_signal (background, NULL);
+ nautilus_background_set_image_uri_no_signal (background, NULL);
+ gtk_signal_emit (GTK_OBJECT (background), signals[SETTINGS_CHANGED]);
+ gtk_signal_emit (GTK_OBJECT (background), signals[APPEARANCE_CHANGED]);
}
static void
@@ -974,9 +1012,11 @@ nautilus_background_receive_dropped_color (NautilusBackground *background,
g_free (color_spec);
- nautilus_background_set_color (background, new_gradient_spec);
- nautilus_background_set_image_uri (background, NULL);
-
+ nautilus_background_set_color_no_signal (background, new_gradient_spec);
+ nautilus_background_set_image_uri_no_signal (background, NULL);
+ gtk_signal_emit (GTK_OBJECT (background), signals[SETTINGS_CHANGED]);
+ gtk_signal_emit (GTK_OBJECT (background), signals[APPEARANCE_CHANGED]);
+
g_free (new_gradient_spec);
}
diff --git a/libnautilus-private/nautilus-background.h b/libnautilus-private/nautilus-background.h
index 843ebb164..1e653601d 100644
--- a/libnautilus-private/nautilus-background.h
+++ b/libnautilus-private/nautilus-background.h
@@ -80,12 +80,13 @@ void nautilus_background_set_image_placement (Nautil
/* Calls to interrogate the current state of a background. */
char * nautilus_background_get_color (NautilusBackground *background);
-char * nautilus_background_get_image_uri (NautilusBackground *background);
+char * nautilus_background_get_image_uri (NautilusBackground *background);
gboolean nautilus_background_get_combine_mode (NautilusBackground *background);
nautilus_background_image_placement
nautilus_background_get_image_placement (NautilusBackground *background);
gboolean nautilus_background_is_dark (NautilusBackground *background);
gboolean nautilus_background_is_set (NautilusBackground *background);
+gboolean nautilus_background_is_loaded (NautilusBackground *background);
/* Explicitly fills a rectangle with a background. */
void nautilus_background_draw (NautilusBackground *background,
@@ -141,6 +142,10 @@ struct NautilusBackgroundClass
*/
void (* appearance_changed) (NautilusBackground *);
+ /* This signal is emitted whenever an image is loaded.
+ */
+ void (* image_loaded) (NautilusBackground *);
+
/* This signal is emitted when the background is reset by receiving
the reset property from a drag */
diff --git a/libnautilus-private/nautilus-directory-background.c b/libnautilus-private/nautilus-directory-background.c
index d5812cfbc..9f08dbbf7 100644
--- a/libnautilus-private/nautilus-directory-background.c
+++ b/libnautilus-private/nautilus-directory-background.c
@@ -36,13 +36,16 @@
#include "nautilus-theme.h"
#include "libnautilus-extensions/nautilus-gdk-extensions.h"
+#include <gdk/gdkx.h>
+#include <X11/Xatom.h>
+
static void background_changed_callback (NautilusBackground *background,
NautilusDirectory *directory);
static void directory_changed_callback (NautilusDirectory *directory,
NautilusBackground *background);
static void background_reset_callback (NautilusBackground *background,
NautilusDirectory *directory);
-
+
void
static nautilus_directory_background_set_desktop (NautilusBackground *background)
{
@@ -257,10 +260,6 @@ nautilus_directory_background_write_desktop_settings (char *color, char *image,
}
gnome_config_sync ();
-
- /* FIXME
- * Try to trick GNOME into re-reading the settings.
- */
}
static void
@@ -272,7 +271,138 @@ nautilus_directory_background_write_desktop_default_settings ()
nautilus_background_image_placement placement;
nautilus_directory_background_get_default_settings (TRUE, &color, &image, &placement, &combine);
nautilus_directory_background_write_desktop_settings (color, image, placement, combine);
-}
+}
+
+/* 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)
+{
+ Pixmap result;
+
+ gdk_flush ();
+
+ XSetCloseDownMode (gdk_display, RetainPermanent);
+
+ result = XCreatePixmap (gdk_display,
+ DefaultRootWindow (gdk_display),
+ width, height,
+ DefaultDepthOfScreen (DefaultScreenOfDisplay (GDK_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)
+{
+ GdkAtom type;
+ gulong nitems, bytes_after;
+ gint format;
+ guchar *data_esetroot;
+ Pixmap pixmap_id = GDK_WINDOW_XWINDOW (pixmap);
+
+ XGrabServer (GDK_DISPLAY());
+
+ 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 (type == XA_PIXMAP) {
+ if (format == 32 && nitems == 4)
+ XKillClient(GDK_DISPLAY(), *((Pixmap*)data_esetroot));
+
+ XFree (data_esetroot);
+ }
+
+ 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_loaded_callback (NautilusBackground *background, void *calledDirectly)
+{
+ GdkGC *gc;
+ GdkPixmap *bg_pixmap;
+ GdkRectangle screen_rectangle;
+
+ g_assert (NAUTILUS_IS_BACKGROUND (background));
+
+ if (!(gboolean) calledDirectly) {
+ gtk_signal_disconnect_by_func (GTK_OBJECT (background),
+ GTK_SIGNAL_FUNC (image_loaded_callback),
+ calledDirectly);
+ }
+
+ screen_rectangle.x = 0;
+ screen_rectangle.y = 0;
+ screen_rectangle.width = gdk_screen_width ();
+ screen_rectangle.height = gdk_screen_height ();
+
+ bg_pixmap = make_root_pixmap (screen_rectangle.width, screen_rectangle.height);
+ gc = gdk_gc_new (bg_pixmap);
+
+ nautilus_background_draw (background, bg_pixmap, gc, &screen_rectangle, 0, 0);
+
+ set_root_pixmap (bg_pixmap);
+
+ dispose_root_pixmap (bg_pixmap);
+ gdk_gc_unref (gc);
+}
+
+static void
+nautilus_directory_update_root_window (NautilusBackground *background)
+{
+ if (nautilus_background_is_loaded (background)) {
+ image_loaded_callback (background, (void *) TRUE);
+ } else {
+ gtk_signal_connect (GTK_OBJECT (background),
+ "image_loaded",
+ GTK_SIGNAL_FUNC (image_loaded_callback),
+ (void *) FALSE);
+ }
+}
/* return true if the background is not in the default state */
gboolean
@@ -353,6 +483,10 @@ background_changed_callback (NautilusBackground *background,
g_free (color);
g_free (image);
+
+ if (nautilus_directory_background_is_desktop (background)) {
+ nautilus_directory_update_root_window (background);
+ }
}
/* handle the directory changed signal */
@@ -461,6 +595,10 @@ background_reset_callback (NautilusBackground *background,
* It will set color and image_uri to NULL.
*/
gtk_signal_emit_stop_by_name (GTK_OBJECT (background), "reset");
+
+ if (nautilus_directory_background_is_desktop (background)) {
+ nautilus_directory_update_root_window (background);
+ }
}
/* handle the background destroyed signal */