1 /* xscreensaver, Copyright (c) 1997 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 /* This is a kludge that lets xscreensaver work with SGI demos that expect
13 to be run from `haven'. It runs the program given on the command line,
14 then waits for an X window to be created whose name is that of the
15 program. Then, it resizes that window to fill the screen. Run it
18 xscreensaver-sgigl /usr/demos/bin/ep -S
19 xscreensaver-sgigl -n ant /usr/demos/General_Demos/ant/RUN
20 xscreensaver-sgigl -n atlantis /usr/demos/General_Demos/atlantis/RUN
21 xscreensaver-sgigl -n /usr/demos/General_Demos/powerflip/powerflip \
22 /usr/demos/General_Demos/powerflip/RUN
24 Except that doesn't really work. You have to do this instead:
26 xscreensaver-sgigl -n ant ant.sh
31 cd /usr/demos/General_Demos/ant
34 There's no way to make this work with powerflip at all, since it doesn't
35 take a -S option to run in the foreground.
38 /* #### Another way to do this would be:
39 instead of exec'ing the hack, fork it; then wait for that fork to die.
40 If it dies, but the window ID is still valid, then that means the
41 sub-process has forked itself (as those fuckwits at SGI are wont to do.)
42 In that case, this process should go to sleep, and set up a signal handler
43 that will destroy the X window when it is killed. That way, the caller
44 is given a foreground pid which, when killed, will cause the hack to die
45 (by a roundabout mechanism.)
47 This would all be so much simpler if those assholes would just:
49 1: get out of the habit of writing programs that magically background
52 2: give the fucking programs arguments which control the window size
53 instead of always making 100x100 windows!
55 I won't even dream of having a "-root" option that understood virtual-roots;
56 that would just be too outlandish to even dream about.
59 static char *progname;
67 #include <X11/Xmu/Error.h>
70 #undef RootWindowOfScreen
72 #undef DefaultRootWindow
76 BadWindow_ehandler (Display *dpy, XErrorEvent *error)
78 if (error->error_code == BadWindow ||
79 error->error_code == BadMatch ||
80 error->error_code == BadDrawable)
84 fprintf (stderr, "\nX error in %s:\n", progname);
85 if (XmuPrintDefaultErrorMessage (dpy, error, stderr))
88 fprintf (stderr, " (nonfatal.)\n");
95 main(int ac, char **av)
104 Bool verbose = False;
109 s = strrchr(progname, '/');
110 if (s) progname = s+1;
115 "usage: %s [ -v ] [ -n window-name ] program arguments...\n",
120 if (ac > 2 && !strcmp(av[1], "-v"))
127 if (ac > 2 && !strcmp(av[1], "-n"))
134 n1 = strrchr(av[1], '/');
139 dpy = XOpenDisplay(0);
142 fprintf(stderr, "%s: couldn't open display\n", progname);
146 screen = DefaultScreenOfDisplay(dpy);
147 root = XRootWindowOfScreen (screen);
148 vroot = VirtualRootWindowOfScreen (screen);
150 XSelectInput (dpy, root, SubstructureNotifyMask);
152 XSelectInput (dpy, vroot, SubstructureNotifyMask);
154 XSetErrorHandler (BadWindow_ehandler);
157 fprintf(stderr, "%s: selected SubstructureNotifyMask on 0x%x / 0x%x\n",
158 progname, root, vroot);
163 fprintf(stderr, "%s: pid is %d\n", progname, parent);
165 switch ((int) (forked = fork ()))
169 sprintf (buf, "%s: couldn't fork", progname);
176 time_t start = time((time_t) 0);
180 fprintf(stderr, "%s: forked pid is %d\n", progname, getpid());
184 XNextEvent(dpy, &event);
186 if (event.xany.type == CreateNotify)
189 Window w = event.xcreatewindow.window;
192 XFetchName(dpy, w, &name);
195 /* Try again to see if the name has been set later... */
198 XFetchName(dpy, w, &name);
202 ((n1 && !strcmp(name, n1)) ||
203 (n2 && !strcmp(name, n2))))
206 fprintf(stderr, "%s: resizing 0x%x\n", progname, w);
208 XMoveResizeWindow(dpy, w, 0, 0,
209 WidthOfScreen(screen),
210 HeightOfScreen(screen));
213 if (vroot && vroot != root &&
214 event.xcreatewindow.parent == root)
218 "%s: reparenting 0x%x from 0x%x to 0x%x\n",
219 progname, w, root, vroot);
220 XReparentWindow(dpy, w, vroot, 0, 0);
227 exit(0); /* Note that this only exits a child fork. */
231 if (start + 5 < time((time_t) 0))
234 "%s: timed out: no window named \"%s\" has been created\n",
235 progname, (n2 ? n2 : n1));
238 kill(parent, SIGTERM);
244 default: /* foreground */
246 close (ConnectionNumber (dpy)); /* close display fd */
247 execvp (av[1], av+1); /* shouldn't return. */
248 sprintf (buf, "%s: execvp(\"%s\") failed", progname, av[1]);