summaryrefslogtreecommitdiff
path: root/libnautilus-private/nautilus-directory-background.c
diff options
context:
space:
mode:
Diffstat (limited to 'libnautilus-private/nautilus-directory-background.c')
-rw-r--r--libnautilus-private/nautilus-directory-background.c150
1 files changed, 144 insertions, 6 deletions
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 */