X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?p=xscreensaver;a=blobdiff_plain;f=driver%2Fxscreensaver-getimage.c;h=7b8919774ae422c63b7d3534ae2ad9dc1cc28522;hp=e46bc5c97262a6e9d55ce566c0142ec8c4b25228;hb=ffd8c0873576a9e3065696a624dce6b766b77062;hpb=96a411663168b0ba5432b407a83be55f3df0c802 diff --git a/driver/xscreensaver-getimage.c b/driver/xscreensaver-getimage.c index e46bc5c9..7b891977 100644 --- a/driver/xscreensaver-getimage.c +++ b/driver/xscreensaver-getimage.c @@ -1,4 +1,4 @@ -/* xscreensaver, Copyright (c) 2001, 2002, 2003 by Jamie Zawinski +/* xscreensaver, Copyright (c) 2001-2004 by Jamie Zawinski * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -136,6 +136,15 @@ ignore_all_errors_ehandler (Display *dpy, XErrorEvent *error) return 0; } +static int +ignore_badmatch_ehandler (Display *dpy, XErrorEvent *error) +{ + if (error->error_code == BadMatch) + return ignore_all_errors_ehandler (dpy, error); + else + return x_ehandler (dpy, error); +} + /* Returns True if the given Drawable is a Window; False if it's a Pixmap. */ @@ -171,7 +180,7 @@ root_window_p (Screen *screen, Window window) Atom type; int format; unsigned long nitems, bytesafter; - char *version; + unsigned char *version; if (window != RootWindowOfScreen (screen)) return False; @@ -180,7 +189,7 @@ root_window_p (Screen *screen, Window window) XInternAtom (dpy, "_SCREENSAVER_VERSION", False), 0, 1, False, XA_STRING, &type, &format, &nitems, &bytesafter, - (unsigned char **) &version) + &version) == Success && type != None) return False; @@ -885,7 +894,7 @@ read_jpeg_ximage (Screen *screen, Visual *visual, Drawable drawable, int x; for (x = 0; x < ximage->width; x++) { - int j = x * cinfo.num_components; + int j = x * cinfo.output_components; unsigned char r = scanbuf[i][j]; unsigned char g = scanbuf[i][j+1]; unsigned char b = scanbuf[i][j+2]; @@ -897,10 +906,12 @@ read_jpeg_ximage (Screen *screen, Visual *visual, Drawable drawable, pixel = ((r >> 5) | ((g >> 5) << 3) | ((b >> 6) << 6)); else if (depth == 12) pixel = ((r >> 4) | ((g >> 4) << 4) | ((b >> 4) << 8)); - else if (depth == 16 || depth == 15) + else if (depth == 15) /* Gah! I don't understand why these are in the other order. */ pixel = (((r >> 3) << 10) | ((g >> 3) << 5) | ((b >> 3))); + else if (depth == 16) + pixel = (((r >> 3) << 11) | ((g >> 2) << 5) | ((b >> 3))); else abort(); @@ -1347,12 +1358,38 @@ display_desktop (Screen *screen, Window window, Drawable drawable, } else /* size mismatch -- must scale client-side images to fit drawable */ { - XImage *ximage = XGetImage (dpy, window, 0, 0, xgwa.width, xgwa.height, - ~0L, ZPixmap); GC gc; + XImage *ximage = 0; + XErrorHandler old_handler; + + XSync (dpy, False); + old_handler = XSetErrorHandler (ignore_badmatch_ehandler); + error_handler_hit_p = False; + + /* This can return BadMatch if the window is not fully on screen. + Trap that error and return color bars in that case. + (Note that this only happens with XGetImage, not with XCopyArea: + yet another totally gratuitous inconsistency in X, thanks.) + */ + ximage = XGetImage (dpy, window, 0, 0, xgwa.width, xgwa.height, + ~0L, ZPixmap); + + XSync (dpy, False); + XSetErrorHandler (old_handler); + XSync (dpy, False); + + if (error_handler_hit_p) + { + ximage = 0; + if (verbose_p) + fprintf (stderr, "%s: BadMatch reading window 0x%x contents!\n", + progname, (unsigned int) window); + } + if (!ximage || !scale_ximage (xgwa.screen, xgwa.visual, ximage, w2, h2)) return False; + gc = XCreateGC (dpy, drawable, 0, &gcv); clear_drawable (screen, drawable); XPutImage (dpy, drawable, gc, ximage, @@ -1442,8 +1479,7 @@ get_image (Screen *screen, video_p = False; image_p = True; } - - if (!dir || !*dir) + else if (!dir || !*dir) { if (verbose_p && image_p) fprintf (stderr,