diff -r -U12 gnome-screensaver.orig/savers/gste-slideshow.c gnome-screensaver/savers/gste-slideshow.c
--- gnome-screensaver.orig/savers/gste-slideshow.c	2006-05-23 02:55:49.000000000 -0700
+++ gnome-screensaver/savers/gste-slideshow.c	2006-05-23 09:59:02.000000000 -0700
@@ -427,34 +427,55 @@
                                                      show->priv->pixbuf1,
                                                      x, y);
                         cairo_paint (cr);
                 }
         }
 
         cairo_destroy (cr);
 }
 
 static gboolean
 draw_iter (GSTESlideshow *show)
 {
-        gdouble      max_alpha = 1.0;
-
         if (show->priv->pixbuf2) {
                 /* we are in a fade */
                 show->priv->fade_ticks++;
-                show->priv->alpha2 = max_alpha * (double)show->priv->fade_ticks / (double)N_FADE_TICKS;
+
+                /*
+                 * We have currently drawn pat2 with old_opacity, and we
+                 * want to set alpha2 so that drawing pat2 at alpha2
+                 * yields it drawn with new_opacity
+                 *
+                 * Solving
+                 *   new_opacity = 1 - (1 - alpha2) * (1 - old_opacity)
+                 * yields
+                 *   alpha2 = 1 - (1 - new_opacity) / (1 - old_opacity)
+                 *
+                 * Note that any rounding error is guaranteed to be
+                 * cleaned up by the last iteration, where alpha2
+                 * becomes 1 because new_opacity is 1.
+                 *
+                 * XXX Does this make bad assumptions about color
+                 * profiles?
+                 */
+                double old_opacity = (double) (show->priv->fade_ticks - 1) /
+                                     (double) N_FADE_TICKS;
+                double new_opacity = (double) show->priv->fade_ticks /
+                                     (double) N_FADE_TICKS;
+                show->priv->alpha2 = 1.0 - (1.0 - new_opacity) /
+                                           (1.0 - old_opacity);
 
                 update_display (show);
 
-                if (show->priv->alpha2 >= max_alpha) {
+                if (show->priv->fade_ticks >= N_FADE_TICKS) {
                         finish_fade (show);
                 }
         }
 
         return TRUE;
 }
 
 static void
 process_new_pixbuf (GSTESlideshow *show,
                     GdkPixbuf     *pixbuf)
 {
         if (pixbuf) {
