-/* xscreensaver, Copyright (c) 1992, 1993, 1994, 1997, 1998, 2001
+/* xscreensaver, Copyright (c) 1992, 1993, 1994, 1997, 1998, 2001, 2003
* Jamie Zawinski <jwz@jwz.org>
*
* Permission to use, copy, modify, distribute, and sell this software and its
extern char *progname;
+static Bool error_handler_hit_p = False;
+
+static int
+ignore_all_errors_ehandler (Display *dpy, XErrorEvent *error)
+{
+ error_handler_hit_p = True;
+ return 0;
+}
+
+
+/* Returns True if the given Drawable is a Window; False if it's a Pixmap.
+ */
+static Bool
+drawable_window_p (Display *dpy, Drawable d)
+{
+ XErrorHandler old_handler;
+ XWindowAttributes xgwa;
+
+ XSync (dpy, False);
+ old_handler = XSetErrorHandler (ignore_all_errors_ehandler);
+ error_handler_hit_p = False;
+ XGetWindowAttributes (dpy, d, &xgwa);
+ XSync (dpy, False);
+ XSetErrorHandler (old_handler);
+ XSync (dpy, False);
+
+ if (!error_handler_hit_p)
+ return True; /* It's a Window. */
+ else
+ return False; /* It's a Pixmap, or an invalid ID. */
+}
+
+
static Bool
xscreensaver_window_p (Display *dpy, Window window)
{
static void
-checkerboard (Screen *screen, Window window)
+checkerboard (Screen *screen, Drawable drawable)
{
Display *dpy = DisplayOfScreen (screen);
int x, y;
int size = 24;
XColor fg, bg;
XGCValues gcv;
- GC gc = XCreateGC (dpy, window, 0, &gcv);
- XWindowAttributes xgwa;
- XGetWindowAttributes (dpy, window, &xgwa);
+ GC gc = XCreateGC (dpy, drawable, 0, &gcv);
+ Colormap cmap;
+ int win_width, win_height;
+
fg.flags = bg.flags = DoRed|DoGreen|DoBlue;
fg.red = fg.green = fg.blue = 0x0000;
bg.red = bg.green = bg.blue = 0x4444;
fg.pixel = 0;
bg.pixel = 1;
+ if (drawable_window_p (dpy, drawable))
+ {
+ XWindowAttributes xgwa;
+ XGetWindowAttributes (dpy, drawable, &xgwa);
+ win_width = xgwa.width;
+ win_height = xgwa.height;
+ cmap = xgwa.colormap;
+ screen = xgwa.screen;
+ }
+ else /* it's a pixmap */
+ {
+ XWindowAttributes xgwa;
+ Window root;
+ int x, y;
+ unsigned int bw, d;
+ XGetWindowAttributes (dpy, RootWindowOfScreen (screen), &xgwa);
+ cmap = xgwa.colormap;
+ XGetGeometry (dpy, drawable,
+ &root, &x, &y, &win_width, &win_height, &bw, &d);
+ }
+
/* Allocate black and gray, but don't hold them locked. */
- if (XAllocColor (dpy, xgwa.colormap, &fg))
- XFreeColors (dpy, xgwa.colormap, &fg.pixel, 1, 0);
- if (XAllocColor (dpy, xgwa.colormap, &bg))
- XFreeColors (dpy, xgwa.colormap, &bg.pixel, 1, 0);
+ if (XAllocColor (dpy, cmap, &fg))
+ XFreeColors (dpy, cmap, &fg.pixel, 1, 0);
+ if (XAllocColor (dpy, cmap, &bg))
+ XFreeColors (dpy, cmap, &bg.pixel, 1, 0);
XSetForeground (dpy, gc, bg.pixel);
- XFillRectangle (dpy, window, gc, 0, 0, xgwa.width, xgwa.height);
+ XFillRectangle (dpy, drawable, gc, 0, 0, win_width, win_height);
XSetForeground (dpy, gc, fg.pixel);
- for (y = 0; y < xgwa.height; y += size+size)
- for (x = 0; x < xgwa.width; x += size+size)
+ for (y = 0; y < win_height; y += size+size)
+ for (x = 0; x < win_width; x += size+size)
{
- XFillRectangle (dpy, window, gc, x, y, size, size);
- XFillRectangle (dpy, window, gc, x+size, y+size, size, size);
+ XFillRectangle (dpy, drawable, gc, x, y, size, size);
+ XFillRectangle (dpy, drawable, gc, x+size, y+size, size, size);
}
}
+static void
+hack_subproc_environment (Display *dpy)
+{
+ /* Store $DISPLAY into the environment, so that the $DISPLAY variable that
+ the spawned processes inherit is what we are actually using.
+ */
+ const char *odpy = DisplayString (dpy);
+ char *ndpy = (char *) malloc(strlen(odpy) + 20);
+ strcpy (ndpy, "DISPLAY=");
+ strcat (ndpy, odpy);
+
+ /* Allegedly, BSD 4.3 didn't have putenv(), but nobody runs such systems
+ any more, right? It's not Posix, but everyone seems to have it. */
+#ifdef HAVE_PUTENV
+ if (putenv (ndpy))
+ abort ();
+#endif /* HAVE_PUTENV */
+}
+
+
+/* Loads an image into the Drawable.
+ When grabbing desktop images, the Window will be unmapped first.
+ */
void
-grab_screen_image (Screen *screen, Window window)
+load_random_image (Screen *screen, Window window, Drawable drawable)
{
Display *dpy = DisplayOfScreen (screen);
char *grabber = get_string_resource ("desktopGrabber", "DesktopGrabber");
char *cmd;
- char id[20];
+ char id[200];
if (!grabber || !*grabber)
{
exit (1);
}
- sprintf (id, "0x%x", (unsigned long) window);
+ sprintf (id, "0x%lx 0x%lx",
+ (unsigned long) window,
+ (unsigned long) drawable);
cmd = (char *) malloc (strlen(grabber) + strlen(id) + 1);
/* Needn't worry about buffer overflows here, because the buffer is
/* In case "cmd" fails, leave some random image on the screen, not just
black or white, so that it's more obvious what went wrong. */
- checkerboard (screen, window);
+ checkerboard (screen, drawable);
XSync (dpy, True);
+ hack_subproc_environment (dpy);
system (cmd);
free (cmd);
XSync (dpy, True);