1 /* xscreensaver, Copyright (c) 2001 by Jamie Zawinski <jwz@jwz.org>
3 * Permission to use, copy, modify, distribute, and sell this software and its
4 * documentation for any purpose is hereby granted without fee, provided that
5 * the above copyright notice appear in all copies and that both that
6 * copyright notice and this permission notice appear in supporting
7 * documentation. No representations are made about the suitability of this
8 * software for any purpose. It is provided "as is" without express or
12 /* xscreensaver-getimage -- helper program that puts an image
13 (e.g., a snapshot of the desktop) onto the given window.
18 #include <X11/Intrinsic.h>
23 # include <X11/Xmu/Error.h>
25 # include <Xmu/Error.h>
32 #include "grabscreen.h"
33 #include "resources.h"
34 #include "colorbars.h"
39 static char *defaults[] = {
40 #include "../driver/XScreenSaver_ad.h"
47 char *progclass = "XScreenSaver";
51 extern void grabscreen_verbose (void);
54 #define GETIMAGE_VIDEO_PROGRAM "xscreensaver-getimage-video"
55 #define GETIMAGE_FILE_PROGRAM "xscreensaver-getimage-file"
66 exec_error (char **av)
71 sprintf (buf, "%s: could not execute \"%s\"", progname, av[0]);
74 if (errno == ENOENT &&
75 (token = getenv("PATH")))
79 # define PATH_MAX MAXPATHLEN
81 # define PATH_MAX 2048
85 fprintf (stderr, "\n");
87 # if defined(HAVE_GETCWD)
88 getcwd (path, sizeof(path));
89 # elif defined(HAVE_GETWD)
93 fprintf (stderr, " Current directory is: %s\n", path);
94 fprintf (stderr, " PATH is:\n");
95 token = strtok (strdup(token), ":");
98 fprintf (stderr, " %s\n", token);
99 token = strtok(0, ":");
101 fprintf (stderr, "\n");
108 x_ehandler (Display *dpy, XErrorEvent *error)
110 fprintf (stderr, "\nX error in %s:\n", progname);
111 if (XmuPrintDefaultErrorMessage (dpy, error, stderr))
114 fprintf (stderr, " (nonfatal.)\n");
121 get_image (Screen *screen, Window window, Bool verbose_p)
123 Display *dpy = DisplayOfScreen (screen);
124 Bool desk_p = get_boolean_resource ("grabDesktopImages", "Boolean");
125 Bool video_p = get_boolean_resource ("grabVideoFrames", "Boolean");
126 Bool image_p = get_boolean_resource ("chooseRandomImages", "Boolean");
127 char *dir = get_string_resource ("imageDirectory", "ImageDirectory");
129 enum { do_desk, do_video, do_image, do_bars } which = do_bars;
134 fprintf (stderr, "%s: grabDesktopImages: %s\n",
135 progname, desk_p ? "True" : "False");
136 fprintf (stderr, "%s: grabVideoFrames: %s\n",
137 progname, video_p ? "True" : "False");
138 fprintf (stderr, "%s: chooseRandomImages: %s\n",
139 progname, image_p ? "True" : "False");
140 fprintf (stderr, "%s: imageDirectory: %s\n",
141 progname, (dir ? dir : ""));
146 if (verbose_p && image_p)
148 "%s: no imageDirectory: turning off chooseRandomImages.\n",
154 # error Error! This file definitely needs vroot.h!
157 /* If the window is not the root window (real or virtual!) then the hack
158 that called this program is running in "-window" mode instead of in
161 If the window is not the root window, then it's not possible to grab
162 video or images onto it (the contract with those programs is to draw on
163 the root.) So turn off those options in that case, and turn on desktop
164 grabbing. (Since we're running in a window on the desktop already, we
165 know it's not a security problem to expose desktop bits.)
168 if ((desk_p || video_p || image_p) &&
169 !top_level_window_p (screen, window))
175 fprintf (stderr, "%s: not a top-level window: using colorbars.\n",
178 else if (window != VirtualRootWindowOfScreen (screen))
180 Bool changed_p = False;
181 if (!desk_p) desk_p = True, changed_p = True;
182 if (video_p) video_p = False, changed_p = True;
183 if (image_p) image_p = False, changed_p = True;
184 if (changed_p && verbose_p)
186 "%s: not running on root window: grabbing desktop.\n",
192 if (video_p) count++;
193 if (image_p) count++;
198 while (1) /* loop until we get one that's permitted */
200 which = (random() % 3);
201 if (which == do_desk && desk_p) break;
202 if (which == do_video && video_p) break;
203 if (which == do_image && image_p) break;
206 if (which == do_desk)
210 fprintf (stderr, "%s: grabbing desktop image\n", progname);
211 grabscreen_verbose();
213 grab_screen_image (screen, window);
216 else if (which == do_bars)
218 XWindowAttributes xgwa;
219 XGetWindowAttributes (dpy, window, &xgwa);
221 fprintf (stderr, "%s: drawing colorbars\n", progname);
222 draw_colorbars (dpy, window, 0, 0, xgwa.width, xgwa.height);
228 memset (av, 0, sizeof(av));
233 fprintf (stderr, "%s: grabbing video\n", progname);
234 av[0] = GETIMAGE_VIDEO_PROGRAM;
238 fprintf (stderr, "%s: loading random image file\n", progname);
239 av[0] = GETIMAGE_FILE_PROGRAM;
250 for (i = (sizeof(av)/sizeof(*av))-1; i > 1; i--)
252 av[1] = strdup ("--verbose");
258 fprintf (stderr, "%s: executing \"", progname);
261 fprintf (stderr, "%s", av[i]);
262 if (av[++i]) fprintf (stderr, " ");
264 fprintf (stderr, "\"\n");
268 /* Store our "-display" argument into the $DISPLAY variable,
269 so that the subprocess gets the right display if the
270 prevailing $DISPLAY is different. */
272 const char *odpy = DisplayString (dpy);
273 char *ndpy = (char *) malloc(strlen(odpy) + 20);
274 strcpy (ndpy, "DISPLAY=");
279 # endif /* HAVE_PUTENV */
281 close (ConnectionNumber (dpy)); /* close display fd */
283 execvp (av[0], av); /* shouldn't return */
291 mapper (XrmDatabase *db, XrmBindingList bindings, XrmQuarkList quarks,
292 XrmRepresentation *type, XrmValue *value, XPointer closure)
295 for (i = 0; quarks[i]; i++)
297 if (bindings[i] == XrmBindTightly)
298 fprintf (stderr, (i == 0 ? "" : "."));
299 else if (bindings[i] == XrmBindLoosely)
300 fprintf (stderr, "*");
302 fprintf (stderr, " ??? ");
303 fprintf(stderr, "%s", XrmQuarkToString (quarks[i]));
306 fprintf (stderr, ": %s\n", (char *) value->addr);
314 main (int argc, char **argv)
320 Window window = (Window) 0;
321 Bool verbose_p = False;
326 s = strrchr (progname, '/');
327 if (s) progname = s+1;
329 /* We must read exactly the same resources as xscreensaver.
330 That means we must have both the same progclass *and* progname,
331 at least as far as the resource database is concerned. So,
332 put "xscreensaver" in argv[0] while initializing Xt.
334 argv[0] = "xscreensaver";
335 toplevel = XtAppInitialize (&app, progclass, 0, 0, &argc, argv,
338 dpy = XtDisplay (toplevel);
339 screen = XtScreen (toplevel);
340 db = XtDatabase (dpy);
342 XtGetApplicationNameAndClass (dpy, &s, &progclass);
343 XSetErrorHandler (x_ehandler);
346 /* half-assed way of avoiding buffer-overrun attacks. */
347 if (strlen (progname) >= 100) progname[100] = 0;
349 for (i = 1; i < argc; i++)
351 if (argv[i][0] == '-' && argv[i][1] == '-') argv[i]++;
352 if (!strcmp (argv[i], "-v") ||
353 !strcmp (argv[i], "-verbose"))
355 else if (window == 0)
360 if (!strcmp (argv[i], "root") ||
361 !strcmp (argv[i], "-root") ||
362 !strcmp (argv[i], "--root"))
363 window = RootWindowOfScreen (screen);
365 else if ((1 == sscanf (argv[i], " 0x%x %c", &w, &dummy) ||
366 1 == sscanf (argv[i], " %d %c", &w, &dummy)) &&
376 "usage: %s [ -display host:dpy.screen ] [ -v ] window-id\n",
378 fprintf (stderr, "\n"
379 "\tThis program puts an image of the desktop on the given window.\n"
380 "\tIt is used by those xscreensaver demos that operate on images.\n"
386 if (window == 0) goto LOSE;
388 /* Randomize -- only need to do this here because this program
389 doesn't use the `screenhack.h' or `lockmore.h' APIs. */
393 memset (&P, 0, sizeof(P));
401 /* Print out all the resources we read. */
403 XrmName name = { 0 };
404 XrmClass class = { 0 };
406 XrmEnumerateDatabase (db, &name, &class, XrmEnumAllLevels, mapper,
411 get_image (screen, window, verbose_p);