Index: eel-background.c
===================================================================
RCS file: /cvs/gnome/eel/eel/eel-background.c,v
retrieving revision 1.45
diff -u -p -r1.45 eel-background.c
--- eel-background.c	5 Feb 2003 18:30:31 -0000	1.45
+++ eel-background.c	12 Mar 2005 23:49:09 -0000
@@ -43,6 +43,7 @@
 #include <libgnomevfs/gnome-vfs-async-ops.h>
 #include <math.h>
 #include <stdio.h>
+#include <X11/Xlib.h>
 
 /* FIXME: This could really be eliminated now */
 typedef struct {
@@ -82,6 +83,11 @@ static void     eel_background_draw_to_c
 static void     eel_background_draw_aa                   (EelBackground *background,
 							  EelCanvasBuf  *buffer);
 					  
+static gboolean eel_background_swap_timeout              (gpointer data);
+static void     eel_background_cancel_swap               (EelBackground *background);
+static void     eel_background_start_swap                (EelBackground *background);
+static void     eel_background_ensure_image_nonswapped   (EelBackground *background);
+
 
 EEL_CLASS_BOILERPLATE (EelBackground, eel_background, GTK_TYPE_OBJECT)
 
@@ -139,6 +145,9 @@ struct EelBackgroundDetails {
 	gboolean background_changes_with_size;
 
 	gboolean use_base;
+	
+	/* Desktop background swap */
+	gulong swap_timeout;
 };
 
 static void
@@ -231,6 +240,7 @@ eel_background_remove_current_image (Eel
 		g_object_unref (background->details->image);
 		background->details->image = NULL;
 	}
+	eel_background_cancel_swap (background);
 }
 
 static void
@@ -545,6 +555,51 @@ eel_background_image_totally_obscures (E
 	}
 }
 
+static gboolean
+eel_background_swap_timeout (gpointer data)
+{	
+	EelBackground *background = EEL_BACKGROUND (data);
+	eel_background_remove_current_image (background);
+	background->details->swap_timeout = 0;
+	return FALSE;
+}
+
+static void
+eel_background_cancel_swap (EelBackground *background)
+{
+    if (background->details->swap_timeout > 0)
+	    {
+		g_source_remove (background->details->swap_timeout);
+		background->details->swap_timeout = 0;
+	    }
+}
+
+static void
+eel_background_start_swap (EelBackground *background)
+{
+    if (g_object_get_data (G_OBJECT (background), "is_desktop") == 0) 	
+	    return;
+    if (background->details->image_uri == NULL || background->details->image == NULL) 	
+	    return;
+
+    if (background->details->swap_timeout > 0)
+		g_source_remove (background->details->swap_timeout);
+    background->details->swap_timeout =
+       g_timeout_add (30000, eel_background_swap_timeout, background);	
+}
+
+static void
+eel_background_ensure_image_nonswapped (EelBackground *background)
+{
+    if (g_object_get_data (G_OBJECT (background), "is_desktop") == 0)
+	return;
+
+    if (background->details->image_uri != NULL && background->details->image == NULL)
+			eel_background_start_loading_image (background, FALSE, FALSE);
+    eel_background_start_swap (background);
+    return;
+}
+
 static void
 eel_background_ensure_image_scaled (EelBackground *background, int dest_width, int dest_height)
 {
@@ -709,6 +764,54 @@ eel_background_unrealize (EelBackground 
 	background->details->background_entire_height = 0;
 }
 
+static GdkPixmap *
+make_root_pixmap (GdkWindow *window, gint width, gint height)
+{
+	Display *display;
+        const char *display_name;
+	Pixmap result;
+	GdkPixmap *gdk_pixmap;
+	GdkScreen *screen;
+	int screen_num;
+	
+	screen = gdk_drawable_get_screen (window);
+	
+	g_return_val_if_fail (screen != NULL, NULL);
+	
+	screen_num = gdk_screen_get_number (screen);
+
+	gdk_flush ();
+
+	display_name = gdk_display_get_name (gdk_screen_get_display (screen));
+	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;
+        }
+	
+	/* Desktop background pixmap should be created from 
+	 * dummy X client since most applications will try to
+	 * kill it with XKillClient later when changing pixmap
+	 */
+	
+	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;
+}
+
 static gboolean
 eel_background_ensure_realized (EelBackground *background, GdkWindow *window,
 				int entire_width, int entire_height)
@@ -724,6 +827,8 @@ eel_background_ensure_realized (EelBackg
 
 	/* Try to parse the color spec.  If we fail, default to the style's color */
 
+        eel_background_ensure_image_nonswapped (background);
+
 	start_color_spec = eel_gradient_get_start_color_spec (background->details->color);
 
 	if (start_color_spec && eel_gdk_color_parse (start_color_spec, &color))
@@ -731,14 +836,13 @@ eel_background_ensure_realized (EelBackg
 	else {
 		/* Get the widget to which the window belongs and its style as well */
 		gdk_window_get_user_data (window, (void **) &widget);
-		g_assert (widget != NULL);
-
-		style = gtk_widget_get_style (widget);
-
-		if (background->details->use_base) {
-			background->details->background_color = style->base[GTK_STATE_NORMAL];
-		} else {
-			background->details->background_color = style->bg[GTK_STATE_NORMAL];
+		if (widget != NULL) {
+    			style = gtk_widget_get_style (widget);
+	    		if (background->details->use_base) {
+				background->details->background_color = style->base[GTK_STATE_NORMAL];
+			} else {
+		    		background->details->background_color = style->bg[GTK_STATE_NORMAL];
+			}
 		}
 	}
 
@@ -766,7 +870,12 @@ eel_background_ensure_realized (EelBackg
 	changed = FALSE;
 	if (get_pixmap_size (background, entire_width, entire_height,
 			      &pixmap_width, &pixmap_height, &background->details->background_changes_with_size)) {
-		pixmap = gdk_pixmap_new (window, pixmap_width, pixmap_height, -1);
+		
+		if (g_object_get_data (G_OBJECT (background), "is_desktop") == 0) 	
+			pixmap = gdk_pixmap_new (window, pixmap_width, pixmap_height, -1);
+		else
+			pixmap = make_root_pixmap (window, pixmap_width, pixmap_height);
+		
 		gc = gdk_gc_new (pixmap);
 		eel_background_pre_draw (background,  entire_width, entire_height);
 		eel_background_draw (background, pixmap, gc,
@@ -780,6 +889,8 @@ eel_background_ensure_realized (EelBackg
 	background->details->background_entire_width = entire_width;
 	background->details->background_entire_height = entire_height;
 	
+        eel_background_start_swap (background);
+	
 	return changed;
 }
 
