1 /* xscreensaver, Copyright (c) 2001, 2002 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>
24 # include <X11/Xmu/Error.h>
26 # include <Xmu/Error.h>
33 #include "grabscreen.h"
34 #include "resources.h"
35 #include "colorbars.h"
41 static char *defaults[] = {
42 #include "../driver/XScreenSaver_ad.h"
49 char *progclass = "XScreenSaver";
53 extern void grabscreen_verbose (void);
56 #define GETIMAGE_VIDEO_PROGRAM "xscreensaver-getimage-video"
57 #define GETIMAGE_FILE_PROGRAM "xscreensaver-getimage-file"
68 exec_error (char **av)
73 sprintf (buf, "%s: could not execute \"%s\"", progname, av[0]);
76 if (errno == ENOENT &&
77 (token = getenv("PATH")))
81 # define PATH_MAX MAXPATHLEN
83 # define PATH_MAX 2048
87 fprintf (stderr, "\n");
89 # if defined(HAVE_GETCWD)
90 getcwd (path, sizeof(path));
91 # elif defined(HAVE_GETWD)
95 fprintf (stderr, " Current directory is: %s\n", path);
96 fprintf (stderr, " PATH is:\n");
97 token = strtok (strdup(token), ":");
100 fprintf (stderr, " %s\n", token);
101 token = strtok(0, ":");
103 fprintf (stderr, "\n");
110 x_ehandler (Display *dpy, XErrorEvent *error)
112 fprintf (stderr, "\nX error in %s:\n", progname);
113 XmuPrintDefaultErrorMessage (dpy, error, stderr);
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;
132 XWindowAttributes xgwa;
133 XGetWindowAttributes (dpy, window, &xgwa);
134 screen = xgwa.screen;
138 fprintf (stderr, "%s: grabDesktopImages: %s\n",
139 progname, desk_p ? "True" : "False");
140 fprintf (stderr, "%s: grabVideoFrames: %s\n",
141 progname, video_p ? "True" : "False");
142 fprintf (stderr, "%s: chooseRandomImages: %s\n",
143 progname, image_p ? "True" : "False");
144 fprintf (stderr, "%s: imageDirectory: %s\n",
145 progname, (dir ? dir : ""));
150 if (verbose_p && image_p)
152 "%s: no imageDirectory: turning off chooseRandomImages.\n",
158 # error Error! This file definitely needs vroot.h!
161 /* If the window is not the root window (real or virtual!) then the hack
162 that called this program is running in "-window" mode instead of in
165 If the window is not the root window, then it's not possible to grab
166 video or images onto it (the contract with those programs is to draw on
167 the root.) So turn off those options in that case, and turn on desktop
168 grabbing. (Since we're running in a window on the desktop already, we
169 know it's not a security problem to expose desktop bits.)
172 if ((desk_p || video_p || image_p) &&
173 !top_level_window_p (screen, window))
179 fprintf (stderr, "%s: not a top-level window: using colorbars.\n",
182 else if (window != VirtualRootWindowOfScreen (screen))
184 Bool changed_p = False;
185 if (!desk_p) desk_p = True, changed_p = True;
186 if (video_p) video_p = False, changed_p = True;
187 if (image_p) image_p = False, changed_p = True;
188 if (changed_p && verbose_p)
190 "%s: not running on root window: grabbing desktop.\n",
196 if (video_p) count++;
197 if (image_p) count++;
204 while (1) /* loop until we get one that's permitted */
206 which = (random() % 3);
207 if (which == do_desk && desk_p) break;
208 if (which == do_video && video_p) break;
209 if (which == do_image && image_p) break;
210 if (++i > 200) abort();
214 if (which == do_desk)
218 fprintf (stderr, "%s: grabbing desktop image\n", progname);
219 grabscreen_verbose();
221 grab_screen_image (screen, window);
224 else if (which == do_bars)
227 fprintf (stderr, "%s: drawing colorbars\n", progname);
228 draw_colorbars (dpy, window, 0, 0, xgwa.width, xgwa.height);
234 memset (av, 0, sizeof(av));
239 fprintf (stderr, "%s: grabbing video\n", progname);
240 av[0] = GETIMAGE_VIDEO_PROGRAM;
244 fprintf (stderr, "%s: loading random image file\n", progname);
245 av[0] = GETIMAGE_FILE_PROGRAM;
256 for (i = (sizeof(av)/sizeof(*av))-1; i > 1; i--)
258 av[1] = strdup ("--verbose");
264 fprintf (stderr, "%s: executing \"", progname);
267 fprintf (stderr, "%s", av[i]);
268 if (av[++i]) fprintf (stderr, " ");
270 fprintf (stderr, "\"\n");
274 /* Store our "-display" argument into the $DISPLAY variable,
275 so that the subprocess gets the right display if the
276 prevailing $DISPLAY is different. */
278 const char *odpy = DisplayString (dpy);
279 char *ndpy = (char *) malloc(strlen(odpy) + 20);
281 int screen_no = screen_number (screen); /* might not be default now */
283 strcpy (ndpy, "DISPLAY=");
284 s = ndpy + strlen(ndpy);
287 while (*s && *s != ':') s++; /* skip to colon */
288 while (*s == ':') s++; /* skip over colons */
289 while (isdigit(*s)) s++; /* skip over dpy number */
290 while (*s == '.') s++; /* skip over dot */
291 if (s[-1] != '.') *s++ = '.'; /* put on a dot */
292 sprintf(s, "%d", screen_no); /* put on screen number */
297 /* don't free (ndpy) -- some implementations of putenv (BSD
298 4.4, glibc 2.0) copy the argument, but some (libc4,5, glibc
299 2.1.2) do not. So we must leak it (and/or the previous
303 # endif /* HAVE_PUTENV */
305 close (ConnectionNumber (dpy)); /* close display fd */
307 execvp (av[0], av); /* shouldn't return */
315 mapper (XrmDatabase *db, XrmBindingList bindings, XrmQuarkList quarks,
316 XrmRepresentation *type, XrmValue *value, XPointer closure)
319 for (i = 0; quarks[i]; i++)
321 if (bindings[i] == XrmBindTightly)
322 fprintf (stderr, (i == 0 ? "" : "."));
323 else if (bindings[i] == XrmBindLoosely)
324 fprintf (stderr, "*");
326 fprintf (stderr, " ??? ");
327 fprintf(stderr, "%s", XrmQuarkToString (quarks[i]));
330 fprintf (stderr, ": %s\n", (char *) value->addr);
338 main (int argc, char **argv)
344 Window window = (Window) 0;
345 Bool verbose_p = False;
350 s = strrchr (progname, '/');
351 if (s) progname = s+1;
353 /* We must read exactly the same resources as xscreensaver.
354 That means we must have both the same progclass *and* progname,
355 at least as far as the resource database is concerned. So,
356 put "xscreensaver" in argv[0] while initializing Xt.
358 argv[0] = "xscreensaver";
359 toplevel = XtAppInitialize (&app, progclass, 0, 0, &argc, argv,
362 dpy = XtDisplay (toplevel);
363 screen = XtScreen (toplevel);
364 db = XtDatabase (dpy);
366 XtGetApplicationNameAndClass (dpy, &s, &progclass);
367 XSetErrorHandler (x_ehandler);
370 /* half-assed way of avoiding buffer-overrun attacks. */
371 if (strlen (progname) >= 100) progname[100] = 0;
373 for (i = 1; i < argc; i++)
375 if (argv[i][0] == '-' && argv[i][1] == '-') argv[i]++;
376 if (!strcmp (argv[i], "-v") ||
377 !strcmp (argv[i], "-verbose"))
379 else if (window == 0)
384 if (!strcmp (argv[i], "root") ||
385 !strcmp (argv[i], "-root") ||
386 !strcmp (argv[i], "--root"))
387 window = RootWindowOfScreen (screen);
389 else if ((1 == sscanf (argv[i], " 0x%x %c", &w, &dummy) ||
390 1 == sscanf (argv[i], " %d %c", &w, &dummy)) &&
400 "usage: %s [ -display host:dpy.screen ] [ -v ] window-id\n",
402 fprintf (stderr, "\n"
403 "\tThis program puts an image of the desktop on the given window.\n"
404 "\tIt is used by those xscreensaver demos that operate on images.\n"
410 if (window == 0) goto LOSE;
412 /* Randomize -- only need to do this here because this program
413 doesn't use the `screenhack.h' or `lockmore.h' APIs. */
417 memset (&P, 0, sizeof(P));
425 /* Print out all the resources we read. */
427 XrmName name = { 0 };
428 XrmClass class = { 0 };
430 XrmEnumerateDatabase (db, &name, &class, XrmEnumAllLevels, mapper,
435 get_image (screen, window, verbose_p);