1 /* xscreensaver, Copyright (c) 1992, 1993, 1994, 1997, 1998, 2001, 2003
2 * Jamie Zawinski <jwz@jwz.org>
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation. No representations are made about the suitability of this
9 * software for any purpose. It is provided "as is" without express or
13 /* This file contains code for running an external program to grab an image
14 onto the given window. The external program in question must take a
15 window ID as its argument, e.g., the "xscreensaver-getimage" program
16 in the hacks/ directory.
18 That program links against utils/grabimage.c, which happens to export the
19 same API as this program (utils/grabclient.c).
23 #include "grabscreen.h"
24 #include "resources.h"
27 #include <X11/Xatom.h>
29 extern char *progname;
32 static Bool error_handler_hit_p = False;
35 ignore_all_errors_ehandler (Display *dpy, XErrorEvent *error)
37 error_handler_hit_p = True;
42 /* Returns True if the given Drawable is a Window; False if it's a Pixmap.
45 drawable_window_p (Display *dpy, Drawable d)
47 XErrorHandler old_handler;
48 XWindowAttributes xgwa;
51 old_handler = XSetErrorHandler (ignore_all_errors_ehandler);
52 error_handler_hit_p = False;
53 XGetWindowAttributes (dpy, d, &xgwa);
55 XSetErrorHandler (old_handler);
58 if (!error_handler_hit_p)
59 return True; /* It's a Window. */
61 return False; /* It's a Pixmap, or an invalid ID. */
66 xscreensaver_window_p (Display *dpy, Window window)
70 unsigned long nitems, bytesafter;
72 if (XGetWindowProperty (dpy, window,
73 XInternAtom (dpy, "_SCREENSAVER_VERSION", False),
74 0, 1, False, XA_STRING,
75 &type, &format, &nitems, &bytesafter,
76 (unsigned char **) &version)
84 /* XCopyArea seems not to work right on SGI O2s if you draw in SubwindowMode
85 on a window whose depth is not the maximal depth of the screen? Or
86 something. Anyway, things don't work unless we: use SubwindowMode for
87 the real root window (or a legitimate virtual root window); but do not
88 use SubwindowMode for the xscreensaver window. I make no attempt to
92 use_subwindow_mode_p(Screen *screen, Window window)
94 if (window != VirtualRootWindowOfScreen(screen))
96 else if (xscreensaver_window_p(DisplayOfScreen(screen), window))
104 checkerboard (Screen *screen, Drawable drawable)
106 Display *dpy = DisplayOfScreen (screen);
111 GC gc = XCreateGC (dpy, drawable, 0, &gcv);
113 int win_width, win_height;
115 fg.flags = bg.flags = DoRed|DoGreen|DoBlue;
116 fg.red = fg.green = fg.blue = 0x0000;
117 bg.red = bg.green = bg.blue = 0x4444;
121 if (drawable_window_p (dpy, drawable))
123 XWindowAttributes xgwa;
124 XGetWindowAttributes (dpy, drawable, &xgwa);
125 win_width = xgwa.width;
126 win_height = xgwa.height;
127 cmap = xgwa.colormap;
128 screen = xgwa.screen;
130 else /* it's a pixmap */
132 XWindowAttributes xgwa;
136 XGetWindowAttributes (dpy, RootWindowOfScreen (screen), &xgwa);
137 cmap = xgwa.colormap;
138 XGetGeometry (dpy, drawable,
139 &root, &x, &y, &win_width, &win_height, &bw, &d);
142 /* Allocate black and gray, but don't hold them locked. */
143 if (XAllocColor (dpy, cmap, &fg))
144 XFreeColors (dpy, cmap, &fg.pixel, 1, 0);
145 if (XAllocColor (dpy, cmap, &bg))
146 XFreeColors (dpy, cmap, &bg.pixel, 1, 0);
148 XSetForeground (dpy, gc, bg.pixel);
149 XFillRectangle (dpy, drawable, gc, 0, 0, win_width, win_height);
150 XSetForeground (dpy, gc, fg.pixel);
151 for (y = 0; y < win_height; y += size+size)
152 for (x = 0; x < win_width; x += size+size)
154 XFillRectangle (dpy, drawable, gc, x, y, size, size);
155 XFillRectangle (dpy, drawable, gc, x+size, y+size, size, size);
160 hack_subproc_environment (Display *dpy)
162 /* Store $DISPLAY into the environment, so that the $DISPLAY variable that
163 the spawned processes inherit is what we are actually using.
165 const char *odpy = DisplayString (dpy);
166 char *ndpy = (char *) malloc(strlen(odpy) + 20);
167 strcpy (ndpy, "DISPLAY=");
170 /* Allegedly, BSD 4.3 didn't have putenv(), but nobody runs such systems
171 any more, right? It's not Posix, but everyone seems to have it. */
175 #endif /* HAVE_PUTENV */
179 /* Loads an image into the Drawable.
180 When grabbing desktop images, the Window will be unmapped first.
183 load_random_image (Screen *screen, Window window, Drawable drawable)
185 Display *dpy = DisplayOfScreen (screen);
186 char *grabber = get_string_resource ("desktopGrabber", "DesktopGrabber");
190 if (!grabber || !*grabber)
193 "%s: resources installed incorrectly: \"desktopGrabber\" is unset!\n",
198 sprintf (id, "0x%lx 0x%lx",
199 (unsigned long) window,
200 (unsigned long) drawable);
201 cmd = (char *) malloc (strlen(grabber) + strlen(id) + 1);
203 /* Needn't worry about buffer overflows here, because the buffer is
204 longer than the length of the format string, and the length of what
205 we're putting into it. So the only way to crash would be if the
206 format string itself was corrupted, but that comes from the
207 resource database, and if hostile forces have access to that,
208 then the game is already over.
210 sprintf (cmd, grabber, id);
212 /* In case "cmd" fails, leave some random image on the screen, not just
213 black or white, so that it's more obvious what went wrong. */
214 checkerboard (screen, drawable);
217 hack_subproc_environment (dpy);