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>
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 if (XmuPrintDefaultErrorMessage (dpy, error, stderr))
116 fprintf (stderr, " (nonfatal.)\n");
123 get_image (Screen *screen, Window window, Bool verbose_p)
125 Display *dpy = DisplayOfScreen (screen);
126 Bool desk_p = get_boolean_resource ("grabDesktopImages", "Boolean");
127 Bool video_p = get_boolean_resource ("grabVideoFrames", "Boolean");
128 Bool image_p = get_boolean_resource ("chooseRandomImages", "Boolean");
129 char *dir = get_string_resource ("imageDirectory", "ImageDirectory");
131 enum { do_desk, do_video, do_image, do_bars } which = do_bars;
134 XWindowAttributes xgwa;
135 XGetWindowAttributes (dpy, window, &xgwa);
136 screen = xgwa.screen;
140 fprintf (stderr, "%s: grabDesktopImages: %s\n",
141 progname, desk_p ? "True" : "False");
142 fprintf (stderr, "%s: grabVideoFrames: %s\n",
143 progname, video_p ? "True" : "False");
144 fprintf (stderr, "%s: chooseRandomImages: %s\n",
145 progname, image_p ? "True" : "False");
146 fprintf (stderr, "%s: imageDirectory: %s\n",
147 progname, (dir ? dir : ""));
152 if (verbose_p && image_p)
154 "%s: no imageDirectory: turning off chooseRandomImages.\n",
160 # error Error! This file definitely needs vroot.h!
163 /* If the window is not the root window (real or virtual!) then the hack
164 that called this program is running in "-window" mode instead of in
167 If the window is not the root window, then it's not possible to grab
168 video or images onto it (the contract with those programs is to draw on
169 the root.) So turn off those options in that case, and turn on desktop
170 grabbing. (Since we're running in a window on the desktop already, we
171 know it's not a security problem to expose desktop bits.)
174 if ((desk_p || video_p || image_p) &&
175 !top_level_window_p (screen, window))
181 fprintf (stderr, "%s: not a top-level window: using colorbars.\n",
184 else if (window != VirtualRootWindowOfScreen (screen))
186 Bool changed_p = False;
187 if (!desk_p) desk_p = True, changed_p = True;
188 if (video_p) video_p = False, changed_p = True;
189 if (image_p) image_p = False, changed_p = True;
190 if (changed_p && verbose_p)
192 "%s: not running on root window: grabbing desktop.\n",
198 if (video_p) count++;
199 if (image_p) count++;
206 while (1) /* loop until we get one that's permitted */
208 which = (random() % 3);
209 if (which == do_desk && desk_p) break;
210 if (which == do_video && video_p) break;
211 if (which == do_image && image_p) break;
212 if (++i > 200) abort();
216 if (which == do_desk)
220 fprintf (stderr, "%s: grabbing desktop image\n", progname);
221 grabscreen_verbose();
223 grab_screen_image (screen, window);
226 else if (which == do_bars)
229 fprintf (stderr, "%s: drawing colorbars\n", progname);
230 draw_colorbars (dpy, window, 0, 0, xgwa.width, xgwa.height);
236 memset (av, 0, sizeof(av));
241 fprintf (stderr, "%s: grabbing video\n", progname);
242 av[0] = GETIMAGE_VIDEO_PROGRAM;
246 fprintf (stderr, "%s: loading random image file\n", progname);
247 av[0] = GETIMAGE_FILE_PROGRAM;
258 for (i = (sizeof(av)/sizeof(*av))-1; i > 1; i--)
260 av[1] = strdup ("--verbose");
266 fprintf (stderr, "%s: executing \"", progname);
269 fprintf (stderr, "%s", av[i]);
270 if (av[++i]) fprintf (stderr, " ");
272 fprintf (stderr, "\"\n");
276 /* Store our "-display" argument into the $DISPLAY variable,
277 so that the subprocess gets the right display if the
278 prevailing $DISPLAY is different. */
280 const char *odpy = DisplayString (dpy);
281 char *ndpy = (char *) malloc(strlen(odpy) + 20);
283 int screen_no = screen_number (screen); /* might not be default now */
285 strcpy (ndpy, "DISPLAY=");
286 s = ndpy + strlen(ndpy);
289 while (*s && *s != ':') s++; /* skip to colon */
290 while (*s == ':') s++; /* skip over colons */
291 while (isdigit(*s)) s++; /* skip over dpy number */
292 while (*s == '.') s++; /* skip over dot */
293 if (s[-1] != '.') *s++ = '.'; /* put on a dot */
294 sprintf(s, "%d", screen_no); /* put on screen number */
299 # endif /* HAVE_PUTENV */
301 close (ConnectionNumber (dpy)); /* close display fd */
303 execvp (av[0], av); /* shouldn't return */
311 mapper (XrmDatabase *db, XrmBindingList bindings, XrmQuarkList quarks,
312 XrmRepresentation *type, XrmValue *value, XPointer closure)
315 for (i = 0; quarks[i]; i++)
317 if (bindings[i] == XrmBindTightly)
318 fprintf (stderr, (i == 0 ? "" : "."));
319 else if (bindings[i] == XrmBindLoosely)
320 fprintf (stderr, "*");
322 fprintf (stderr, " ??? ");
323 fprintf(stderr, "%s", XrmQuarkToString (quarks[i]));
326 fprintf (stderr, ": %s\n", (char *) value->addr);
334 main (int argc, char **argv)
340 Window window = (Window) 0;
341 Bool verbose_p = False;
346 s = strrchr (progname, '/');
347 if (s) progname = s+1;
349 /* We must read exactly the same resources as xscreensaver.
350 That means we must have both the same progclass *and* progname,
351 at least as far as the resource database is concerned. So,
352 put "xscreensaver" in argv[0] while initializing Xt.
354 argv[0] = "xscreensaver";
355 toplevel = XtAppInitialize (&app, progclass, 0, 0, &argc, argv,
358 dpy = XtDisplay (toplevel);
359 screen = XtScreen (toplevel);
360 db = XtDatabase (dpy);
362 XtGetApplicationNameAndClass (dpy, &s, &progclass);
363 XSetErrorHandler (x_ehandler);
366 /* half-assed way of avoiding buffer-overrun attacks. */
367 if (strlen (progname) >= 100) progname[100] = 0;
369 for (i = 1; i < argc; i++)
371 if (argv[i][0] == '-' && argv[i][1] == '-') argv[i]++;
372 if (!strcmp (argv[i], "-v") ||
373 !strcmp (argv[i], "-verbose"))
375 else if (window == 0)
380 if (!strcmp (argv[i], "root") ||
381 !strcmp (argv[i], "-root") ||
382 !strcmp (argv[i], "--root"))
383 window = RootWindowOfScreen (screen);
385 else if ((1 == sscanf (argv[i], " 0x%x %c", &w, &dummy) ||
386 1 == sscanf (argv[i], " %d %c", &w, &dummy)) &&
396 "usage: %s [ -display host:dpy.screen ] [ -v ] window-id\n",
398 fprintf (stderr, "\n"
399 "\tThis program puts an image of the desktop on the given window.\n"
400 "\tIt is used by those xscreensaver demos that operate on images.\n"
406 if (window == 0) goto LOSE;
408 /* Randomize -- only need to do this here because this program
409 doesn't use the `screenhack.h' or `lockmore.h' APIs. */
413 memset (&P, 0, sizeof(P));
421 /* Print out all the resources we read. */
423 XrmName name = { 0 };
424 XrmClass class = { 0 };
426 XrmEnumerateDatabase (db, &name, &class, XrmEnumAllLevels, mapper,
431 get_image (screen, window, verbose_p);