From http://www.jwz.org/xscreensaver/xscreensaver-5.36.tar.gz
[xscreensaver] / hacks / twang.c
index 4c434d0dff834a0308a57c3411fbeee3b3163585..7d52a411156bda8047298f13ba6ea15d3acf6514 100644 (file)
@@ -62,7 +62,6 @@ struct state {
   Screen *screen;                 /* the screen to draw on */
   XImage *sourceImage;            /* image source of stuff to draw */
   XImage *workImage;              /* work area image, used when rendering */
-  XImage *backgroundImage;      /* image filled with background pixels */
 
   GC backgroundGC;              /* GC for the background color */
   GC foregroundGC;              /* GC for the foreground color */
@@ -79,6 +78,7 @@ struct state {
 
   time_t start_time;
   async_load_state *img_loader;
+  Pixmap pm;
 
   Bool useShm;         /* whether or not to use xshm */
 #ifdef HAVE_XSHM_EXTENSION
@@ -107,26 +107,16 @@ struct state {
 static void
 grabImage_start (struct state *st, XWindowAttributes *xwa)
 {
-    Pixmap p;
-    GC gc;
-    XGCValues gcv;
-    XFillRectangle (st->dpy, st->window, st->backgroundGC, 0, 0, 
-                   st->windowWidth, st->windowHeight);
-
-    p = XCreatePixmap (st->dpy, st->window,
-                       xwa->width, xwa->height, xwa->depth);
-    gc = XCreateGC (st->dpy, st->window, 0, &gcv);
-    XCopyArea (st->dpy, st->window, p, gc, 0, 0,
-               xwa->width, xwa->height, 0, 0);
-    st->backgroundImage = 
-       XGetImage (st->dpy, p, 0, 0, st->windowWidth, st->windowHeight,
-                  ~0L, ZPixmap);
-    XFreeGC (st->dpy, gc);
-    XFreePixmap (st->dpy, p);
+    /* On MacOS X11, XGetImage on a Window often gets an inexplicable BadMatch,
+       possibly due to the window manager having occluded something?  It seems
+       nondeterministic. Loading the image into a pixmap instead fixes it. */
+    if (st->pm) XFreePixmap (st->dpy, st->pm);
+    st->pm = XCreatePixmap (st->dpy, st->window,
+                            xwa->width, xwa->height, xwa->depth);
 
     st->start_time = time ((time_t *) 0);
     st->img_loader = load_image_async_simple (0, xwa->screen, st->window,
-                                              st->window, 0, 0);
+                                              st->pm, 0, 0);
 }
 
 static void
@@ -137,7 +127,8 @@ grabImage_done (struct state *st)
 
     st->start_time = time ((time_t *) 0);
     if (st->sourceImage) XDestroyImage (st->sourceImage);
-    st->sourceImage = XGetImage (st->dpy, st->window, 0, 0, st->windowWidth, st->windowHeight,
+    st->sourceImage = XGetImage (st->dpy, st->pm, 0, 0,
+                                 st->windowWidth, st->windowHeight,
                             ~0L, ZPixmap);
 
     if (st->workImage) XDestroyImage (st->workImage);
@@ -535,7 +526,8 @@ static void renderFrame (struct state *st)
 {
     int n;
 
-    memcpy (st->workImage->data, st->backgroundImage->data, 
+    /* This assumes black is zero. */
+    memset (st->workImage->data, 0, 
            st->workImage->bytes_per_line * st->workImage->height);
 
     sortTiles (st);
@@ -663,6 +655,7 @@ static void
 twang_free (Display *dpy, Window window, void *closure)
 {
   struct state *st = (struct state *) closure;
+  if (st->pm) XFreePixmap (dpy, st->pm);
   free (st);
 }