http://www.mirrorservice.org/sites/master.us.finkmirrors.net/distfiles/md5/fa43fdd68d...
[xscreensaver] / utils / grabclient.c
index 0acb2853985a962091fe3955e354c83d4d52ab19..92481b20292181a0da98844acc36ea286a2c233a 100644 (file)
@@ -1,4 +1,4 @@
-/* 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)
 {
@@ -68,36 +101,58 @@ use_subwindow_mode_p(Screen *screen, 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);
       }
 }
 
@@ -121,13 +176,16 @@ hack_subproc_environment (Display *dpy)
 }
 
 
+/* 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)
     {
@@ -137,7 +195,9 @@ grab_screen_image (Screen *screen, Window window)
       exit (1);
     }
 
-  sprintf (id, "0x%lx", (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
@@ -151,7 +211,7 @@ grab_screen_image (Screen *screen, Window window)
 
   /* 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);