http://packetstormsecurity.org/UNIX/admin/xscreensaver-3.32.tar.gz
[xscreensaver] / utils / grabclient.c
1 /* xscreensaver, Copyright (c) 1992, 1993, 1994, 1997, 1998, 2001
2  *  Jamie Zawinski <jwz@jwz.org>
3  *
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 
10  * implied warranty.
11  */
12
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.
17
18    That program links against utils/grabimage.c, which happens to export the
19    same API as this program (utils/grabclient.c).
20  */
21
22 #include "utils.h"
23 #include "grabscreen.h"
24 #include "resources.h"
25
26 #include "vroot.h"
27 #include <X11/Xatom.h>
28
29 extern char *progname;
30
31
32 static Bool
33 xscreensaver_window_p (Display *dpy, Window window)
34 {
35   Atom type;
36   int format;
37   unsigned long nitems, bytesafter;
38   char *version;
39   if (XGetWindowProperty (dpy, window,
40                           XInternAtom (dpy, "_SCREENSAVER_VERSION", False),
41                           0, 1, False, XA_STRING,
42                           &type, &format, &nitems, &bytesafter,
43                           (unsigned char **) &version)
44       == Success
45       && type != None)
46     return True;
47   return False;
48 }
49
50
51 /* XCopyArea seems not to work right on SGI O2s if you draw in SubwindowMode
52    on a window whose depth is not the maximal depth of the screen?  Or
53    something.  Anyway, things don't work unless we: use SubwindowMode for
54    the real root window (or a legitimate virtual root window); but do not
55    use SubwindowMode for the xscreensaver window.  I make no attempt to
56    explain.
57  */
58 Bool
59 use_subwindow_mode_p(Screen *screen, Window window)
60 {
61   if (window != VirtualRootWindowOfScreen(screen))
62     return False;
63   else if (xscreensaver_window_p(DisplayOfScreen(screen), window))
64     return False;
65   else
66     return True;
67 }
68
69
70 static void
71 checkerboard (Screen *screen, Window window)
72 {
73   Display *dpy = DisplayOfScreen (screen);
74   int x, y;
75   int size = 24;
76   XColor fg, bg;
77   XGCValues gcv;
78   GC gc = XCreateGC (dpy, window, 0, &gcv);
79   XWindowAttributes xgwa;
80   XGetWindowAttributes (dpy, window, &xgwa);
81   fg.flags = bg.flags = DoRed|DoGreen|DoBlue;
82   fg.red = fg.green = fg.blue = 0x0000;
83   bg.red = bg.green = bg.blue = 0x4444;
84   fg.pixel = 0;
85   bg.pixel = 1;
86
87   /* Allocate black and gray, but don't hold them locked. */
88   if (XAllocColor (dpy, xgwa.colormap, &fg))
89     XFreeColors (dpy, xgwa.colormap, &fg.pixel, 1, 0);
90   if (XAllocColor (dpy, xgwa.colormap, &bg))
91     XFreeColors (dpy, xgwa.colormap, &bg.pixel, 1, 0);
92
93   XSetForeground (dpy, gc, bg.pixel);
94   XFillRectangle (dpy, window, gc, 0, 0, xgwa.width, xgwa.height);
95   XSetForeground (dpy, gc, fg.pixel);
96   for (y = 0; y < xgwa.height; y += size+size)
97     for (x = 0; x < xgwa.width; x += size+size)
98       {
99         XFillRectangle (dpy, window, gc, x,      y,      size, size);
100         XFillRectangle (dpy, window, gc, x+size, y+size, size, size);
101       }
102 }
103
104 void
105 grab_screen_image (Screen *screen, Window window)
106 {
107   Display *dpy = DisplayOfScreen (screen);
108   char *grabber = get_string_resource ("desktopGrabber", "DesktopGrabber");
109   char *cmd;
110   char id[20];
111
112   if (!grabber || !*grabber)
113     {
114       fprintf (stderr,
115          "%s: resources installed incorrectly: \"desktopGrabber\" is unset!\n",
116                progname);
117       exit (1);
118     }
119
120   sprintf (id, "0x%x", (unsigned long) window);
121   cmd = (char *) malloc (strlen(grabber) + strlen(id) + 1);
122
123   /* Needn't worry about buffer overflows here, because the buffer is
124      longer than the length of the format string, and the length of what
125      we're putting into it.  So the only way to crash would be if the
126      format string itself was corrupted, but that comes from the
127      resource database, and if hostile forces have access to that,
128      then the game is already over.
129    */
130   sprintf (cmd, grabber, id);
131
132   /* In case "cmd" fails, leave some random image on the screen, not just
133      black or white, so that it's more obvious what went wrong. */
134   checkerboard (screen, window);
135
136   XSync (dpy, True);
137   system (cmd);
138   free (cmd);
139   XSync (dpy, True);
140 }