+/* Grabs a desktop screen shot onto the window and the drawable.
+ If the window and drawable are not the same size, the image in
+ the drawable is scaled to fit.
+ Returns False if it fails.
+ */
+static Bool
+display_desktop (Screen *screen, Window window, Drawable drawable,
+ Bool verbose_p, XRectangle *geom_ret)
+{
+# ifdef USE_EXTERNAL_SCREEN_GRABBER
+
+ Display *dpy = DisplayOfScreen (screen);
+ Bool top_p = top_level_window_p (screen, window);
+ char *filename;
+ Bool status;
+
+ if (top_p)
+ {
+ if (verbose_p)
+ fprintf (stderr, "%s: unmapping 0x%lx.\n", progname,
+ (unsigned long) window);
+ XUnmapWindow (dpy, window);
+ XSync (dpy, False);
+ }
+
+ filename = get_desktop_filename (screen, verbose_p);
+
+ if (top_p)
+ {
+ if (verbose_p)
+ fprintf (stderr, "%s: mapping 0x%lx.\n", progname,
+ (unsigned long) window);
+ XMapRaised (dpy, window);
+ XSync (dpy, False);
+ }
+
+ if (!filename)
+ {
+ if (verbose_p)
+ fprintf (stderr, "%s: desktop grab failed.\n", progname);
+ return False;
+ }
+
+ status = display_file (screen, window, drawable, filename, verbose_p,
+ geom_ret);
+
+ if (unlink (filename))
+ {
+ char buf[512];
+ sprintf (buf, "%s: rm %.100s", progname, filename);
+ perror (buf);
+ }
+ else if (verbose_p)
+ fprintf (stderr, "%s: rm %s\n", progname, filename);
+
+ if (filename) free (filename);
+ return status;
+
+# else /* !USE_EXTERNAL_SCREEN_GRABBER */
+
+ Display *dpy = DisplayOfScreen (screen);
+ XGCValues gcv;
+ XWindowAttributes xgwa;
+ Window root;
+ int px, py;
+ unsigned int pw, ph, pbw, pd;
+ int srcx, srcy, destx, desty, w2, h2;
+
+ if (verbose_p)
+ {
+ fprintf (stderr, "%s: grabbing desktop image\n", progname);
+ grabscreen_verbose();
+ }
+
+ XGetWindowAttributes (dpy, window, &xgwa);
+ XGetGeometry (dpy, drawable, &root, &px, &py, &pw, &ph, &pbw, &pd);
+
+ grab_screen_image_internal (screen, window);
+
+ compute_image_scaling (xgwa.width, xgwa.height,
+ pw, ph, verbose_p,
+ &srcx, &srcy, &destx, &desty, &w2, &h2);
+
+ if (pw == w2 && ph == h2) /* it fits -- just copy server-side pixmaps */
+ {
+ GC gc = XCreateGC (dpy, drawable, 0, &gcv);
+ XCopyArea (dpy, window, drawable, gc,
+ 0, 0, xgwa.width, xgwa.height, 0, 0);
+ XFreeGC (dpy, gc);
+ }
+ else /* size mismatch -- must scale client-side images to fit drawable */
+ {
+ 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,
+ srcx, srcy, destx, desty, ximage->width, ximage->height);
+ XDestroyImage (ximage);
+ XFreeGC (dpy, gc);
+ }
+
+ if (geom_ret)
+ {
+ geom_ret->x = destx;
+ geom_ret->y = desty;
+ geom_ret->width = w2;
+ geom_ret->height = h2;
+ }
+
+ XSync (dpy, False);
+ return True;
+
+# endif /* !USE_EXTERNAL_SCREEN_GRABBER */
+}
+
+
+/* Whether the given Drawable is unreasonably small.
+ */
+static Bool
+drawable_miniscule_p (Display *dpy, Drawable drawable)
+{
+ Window root;
+ int xx, yy;
+ unsigned int bw, d, w = 0, h = 0;
+ XGetGeometry (dpy, drawable, &root, &xx, &yy, &w, &h, &bw, &d);
+ return (w < 32 || h < 32);
+}
+
+