X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=utils%2Fxshm.c;h=28439c030b92c7041bd2e21b8cf37af5ab7e1ee4;hb=49f5b54f312fe4ac2e9bc47581a72451bd0e8439;hp=d37afa47cd7f8856b31fbb80369cffd959564732;hpb=ce3185de9d9705e259f2b60dd4b5509007fa17d4;p=xscreensaver diff --git a/utils/xshm.c b/utils/xshm.c index d37afa47..28439c03 100644 --- a/utils/xshm.c +++ b/utils/xshm.c @@ -1,4 +1,4 @@ -/* xscreensaver, Copyright (c) 1993, 1994, 1995, 1996, 1997, 1998 +/* xscreensaver, Copyright (c) 1993, 1994, 1995, 1996, 1997, 1998, 2001, 2006 * by Jamie Zawinski * * Permission to use, copy, modify, distribute, and sell this software and its @@ -21,8 +21,7 @@ needed, anyway.) If you don't have man pages for this extension, see - http://www.physik.uni-regensburg.de/~scs22156/sofie-0.2/mit-shm.html - or in the R6 sources as "xc/doc/specs/Xext/mit-shm.ms". + http://www.x.org/X11R6.8.1/docs/Xext/ (This document seems not to ever remain available on the web in one place for very long; you can search for it by the title, "MIT-SHM -- The MIT @@ -35,15 +34,60 @@ #ifdef HAVE_XSHM_EXTENSION /* whole file */ +/* #define DEBUG */ + #include /* for perror() */ #include /* for XDestroyImage() */ #include "xshm.h" #include "resources.h" /* for get_string_resource() */ +#ifdef DEBUG +# include +#endif extern char *progname; + +/* The documentation for the XSHM extension implies that if the server + supports XSHM but is not the local machine, the XShm calls will return + False; but this turns out not to be the case. Instead, the server + throws a BadAccess error. So, we need to catch X errors around all + of our XSHM calls, sigh. + */ + +static Bool shm_got_x_error = False; +XErrorHandler old_handler = 0; +static int +shm_ehandler (Display *dpy, XErrorEvent *error) +{ + shm_got_x_error = True; + +#ifdef DEBUG + fprintf (stderr, "\n%s: ignoring X error from XSHM:\n", progname); + XmuPrintDefaultErrorMessage (dpy, error, stderr); + fprintf (stderr, "\n"); +#endif + + return 0; +} + + +#define CATCH_X_ERROR(DPY) do { \ + XSync((DPY), False); \ + shm_got_x_error = False; \ + if (old_handler != shm_ehandler) \ + old_handler = XSetErrorHandler (shm_ehandler); \ +} while(0) + +#define UNCATCH_X_ERROR(DPY) do { \ + XSync((DPY), False); \ + if (old_handler) \ + XSetErrorHandler (old_handler); \ + old_handler = 0; \ +} while(0) + + XImage * create_xshm_image (Display *dpy, Visual *visual, unsigned int depth, @@ -51,15 +95,21 @@ create_xshm_image (Display *dpy, Visual *visual, XShmSegmentInfo *shm_info, unsigned int width, unsigned int height) { + Status status; XImage *image = 0; - if (!get_boolean_resource("useSHM", "Boolean")) + if (!get_boolean_resource(dpy, "useSHM", "Boolean")) return 0; if (!XShmQueryExtension (dpy)) return 0; + CATCH_X_ERROR(dpy); image = XShmCreateImage(dpy, visual, depth, - format, data, shm_info, width, height); + format, data, shm_info, width, height); + UNCATCH_X_ERROR(dpy); + if (shm_got_x_error) + return 0; + #ifdef DEBUG fprintf(stderr, "\n%s: XShmCreateImage(... %d, %d)\n", progname, width, height); @@ -92,7 +142,13 @@ create_xshm_image (Display *dpy, Visual *visual, shm_info->shmid, (int) image->data); #endif - if (!XShmAttach(dpy, shm_info)) + CATCH_X_ERROR(dpy); + status = XShmAttach(dpy, shm_info); + UNCATCH_X_ERROR(dpy); + if (shm_got_x_error) + status = False; + + if (!status) { fprintf (stderr, "%s: XShmAttach failed!\n", progname); XDestroyImage (image); @@ -100,9 +156,9 @@ create_xshm_image (Display *dpy, Visual *visual, shmdt (shm_info->shmaddr); image = 0; } - #ifdef DEBUG - fprintf(stderr, "%s: XShmAttach(dpy, shm_info) ==> True\n", progname); + else + fprintf(stderr, "%s: XShmAttach(dpy, shm_info) ==> True\n", progname); #endif XSync(dpy, False); @@ -131,4 +187,43 @@ create_xshm_image (Display *dpy, Visual *visual, return image; } + +void +destroy_xshm_image (Display *dpy, XImage *image, XShmSegmentInfo *shm_info) +{ + Status status; + + CATCH_X_ERROR(dpy); + status = XShmDetach (dpy, shm_info); + UNCATCH_X_ERROR(dpy); + if (shm_got_x_error) + status = False; + if (!status) + fprintf (stderr, "%s: XShmDetach failed!\n", progname); +#ifdef DEBUG + else + fprintf (stderr, "%s: XShmDetach(dpy, shm_info) ==> True\n", progname); +#endif + + XDestroyImage (image); + XSync(dpy, False); + + status = shmdt (shm_info->shmaddr); + + if (status != 0) + { + char buf[1024]; + sprintf (buf, "%s: shmdt(0x%lx) failed", progname, + (unsigned long) shm_info->shmaddr); + perror(buf); + } +#ifdef DEBUG + else + fprintf (stderr, "%s: shmdt(shm_info->shmaddr) ==> 0\n", progname); +#endif + + XSync(dpy, False); +} + + #endif /* HAVE_XSHM_EXTENSION */