1 /* xscreensaver, Copyright (c) 1992, 1995, 1997, 1998
2 * Jamie Zawinski <jwz@netscape.com>
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
12 * And remember: X Windows is to graphics hacking as roman numerals are to
13 * the square root of pi.
16 /* This file contains simple code to open a window or draw on the root.
17 The idea being that, when writing a graphics hack, you can just link
18 with this .o to get all of the uninteresting junk out of the way.
20 - create a procedure `screenhack(dpy, window)'
22 - create a variable `char *progclass' which names this program's
25 - create a variable `char defaults []' for the default resources, and
28 - create a variable `XrmOptionDescRec options[]' for the command-line,
29 and null-terminate it.
35 #include <X11/Intrinsic.h>
36 #include <X11/IntrinsicP.h>
37 #include <X11/CoreP.h>
38 #include <X11/Shell.h>
39 #include <X11/StringDefs.h>
42 # include <X11/SGIScheme.h> /* for SgiUseSchemes() */
47 # include <X11/Xmu/Error.h>
49 # include <Xmu/Error.h>
54 #include "screenhack.h"
62 static XrmOptionDescRec default_options [] = {
63 { "-root", ".root", XrmoptionNoArg, "True" },
64 { "-window", ".root", XrmoptionNoArg, "False" },
65 { "-mono", ".mono", XrmoptionNoArg, "True" },
66 { "-install", ".installColormap", XrmoptionNoArg, "True" },
67 { "-noinstall",".installColormap", XrmoptionNoArg, "False" },
68 { "-visual", ".visualID", XrmoptionSepArg, 0 },
69 { "-window-id", ".windowID", XrmoptionSepArg, 0 },
73 static char *default_defaults[] = {
75 "*geometry: 600x480", /* this should be .geometry, but nooooo... */
77 "*installColormap: false",
83 static XrmOptionDescRec *merged_options;
84 static int merged_options_size;
85 static char **merged_defaults;
90 int def_opts_size, opts_size;
91 int def_defaults_size, defaults_size;
93 for (def_opts_size = 0; default_options[def_opts_size].option;
96 for (opts_size = 0; options[opts_size].option; opts_size++)
99 merged_options_size = def_opts_size + opts_size;
100 merged_options = (XrmOptionDescRec *)
101 malloc ((merged_options_size + 1) * sizeof(*default_options));
102 memcpy (merged_options, default_options,
103 (def_opts_size * sizeof(*default_options)));
104 memcpy (merged_options + def_opts_size, options,
105 ((opts_size + 1) * sizeof(*default_options)));
107 for (def_defaults_size = 0; default_defaults[def_defaults_size];
110 for (defaults_size = 0; defaults[defaults_size]; defaults_size++)
112 merged_defaults = (char **)
113 malloc ((def_defaults_size + defaults_size + 1) * sizeof (*defaults));;
114 memcpy (merged_defaults, default_defaults,
115 def_defaults_size * sizeof(*defaults));
116 memcpy (merged_defaults + def_defaults_size, defaults,
117 (defaults_size + 1) * sizeof(*defaults));
121 /* Make the X errors print out the name of this program, so we have some
122 clue which one has a bug when they die under the screensaver.
126 screenhack_ehandler (Display *dpy, XErrorEvent *error)
128 fprintf (stderr, "\nX error in %s:\n", progname);
129 if (XmuPrintDefaultErrorMessage (dpy, error, stderr))
132 fprintf (stderr, " (nonfatal.)\n");
137 MapNotify_event_p (Display *dpy, XEvent *event, XPointer window)
139 return (event->xany.type == MapNotify &&
140 event->xvisibility.window == (Window) window);
145 extern Visual *get_gl_visual (Screen *, const char *, const char *);
149 extern void pre_merge_options (void);
155 main (int argc, char **argv)
164 Window on_window = 0;
166 Boolean dont_clear /*, dont_map */;
170 pre_merge_options ();
175 /* We have to do this on SGI to prevent the background color from being
176 overridden by the current desktop color scheme (we'd like our backgrounds
177 to be black, thanks.) This should be the same as setting the
178 "*useSchemes: none" resource, but it's not -- if that resource is
179 present in the `default_defaults' above, it doesn't work, though it
180 does work when passed as an -xrm arg on the command line. So screw it,
181 turn them off from C instead.
183 SgiUseSchemes ("none");
186 toplevel = XtAppInitialize (&app, progclass, merged_options,
187 merged_options_size, &argc, argv,
188 merged_defaults, 0, 0);
189 dpy = XtDisplay (toplevel);
190 db = XtDatabase (dpy);
191 XtGetApplicationNameAndClass (dpy, &progname, &progclass);
192 XSetErrorHandler (screenhack_ehandler);
195 char *v = (char *) strdup(strchr(screensaver_id, ' '));
196 char *s = (char *) strchr(v, ',');
198 sprintf (version, "%s: from the XScreenSaver%s distribution.",
209 Bool help_p = !strcmp(argv[1], "-help");
210 fprintf (stderr, "%s\n", version);
211 for (s = progclass; *s; s++) fprintf(stderr, " ");
212 fprintf (stderr, " http://people.netscape.com/jwz/xscreensaver/\n\n");
215 fprintf(stderr, "Unrecognised option: %s\n", argv[1]);
216 fprintf (stderr, "Options include: ");
217 for (i = 0; i < merged_options_size; i++)
219 char *sw = merged_options [i].option;
220 Bool argp = (merged_options [i].argKind == XrmoptionSepArg);
221 int size = strlen (sw) + (argp ? 6 : 0) + 2;
224 fprintf (stderr, "\n\t\t ");
228 fprintf (stderr, "%s", sw);
229 if (argp) fprintf (stderr, " <arg>");
230 if (i != merged_options_size - 1) fprintf (stderr, ", ");
232 fprintf (stderr, ".\n");
233 exit (help_p ? 0 : 1);
236 dont_clear = get_boolean_resource ("dontClearRoot", "Boolean");
237 /*dont_map = get_boolean_resource ("dontMapWindow", "Boolean"); */
238 mono_p = get_boolean_resource ("mono", "Boolean");
239 if (CellsOfScreen (DefaultScreenOfDisplay (dpy)) <= 2)
242 root_p = get_boolean_resource ("root", "Boolean");
245 char *s = get_string_resource ("windowID", "WindowID");
247 on_window = get_integer_resource ("windowID", "WindowID");
253 XWindowAttributes xgwa;
254 window = (Window) on_window;
255 XtDestroyWidget (toplevel);
256 XGetWindowAttributes (dpy, window, &xgwa);
257 cmap = xgwa.colormap;
258 visual = xgwa.visual;
262 XWindowAttributes xgwa;
263 window = RootWindowOfScreen (XtScreen (toplevel));
264 XtDestroyWidget (toplevel);
265 XGetWindowAttributes (dpy, window, &xgwa);
266 cmap = xgwa.colormap;
267 visual = xgwa.visual;
271 Boolean def_visual_p;
272 Screen *screen = XtScreen (toplevel);
275 visual = get_gl_visual (screen, "visualID", "VisualID");
277 visual = get_visual_resource (screen, "visualID", "VisualID", False);
280 if (toplevel->core.width <= 0)
281 toplevel->core.width = 600;
282 if (toplevel->core.height <= 0)
283 toplevel->core.height = 480;
285 def_visual_p = (visual == DefaultVisualOfScreen (screen));
292 cmap = XCreateColormap (dpy, RootWindowOfScreen(screen),
294 bg = get_pixel_resource ("background", "Background", dpy, cmap);
295 bd = get_pixel_resource ("borderColor", "Foreground", dpy, cmap);
297 new = XtVaAppCreateShell (progname, progclass,
298 topLevelShellWidgetClass, dpy,
299 XtNmappedWhenManaged, False,
301 XtNdepth, visual_depth (screen, visual),
302 XtNwidth, toplevel->core.width,
303 XtNheight, toplevel->core.height,
305 XtNbackground, (Pixel) bg,
306 XtNborderColor, (Pixel) bd,
308 XtDestroyWidget (toplevel);
310 XtRealizeWidget (toplevel);
311 window = XtWindow (toplevel);
315 XtVaSetValues (toplevel, XtNmappedWhenManaged, False, 0);
316 XtRealizeWidget (toplevel);
317 window = XtWindow (toplevel);
319 if (get_boolean_resource ("installColormap", "InstallColormap"))
321 cmap = XCreateColormap (dpy, window,
322 DefaultVisualOfScreen (XtScreen (toplevel)),
324 XSetWindowColormap (dpy, window, cmap);
328 cmap = DefaultColormap (dpy, DefaultScreen (dpy));
335 XtVaSetValues (toplevel, XtNmappedWhenManaged, False, 0);
336 XtRealizeWidget (toplevel);
341 XtPopup (toplevel, XtGrabNone);
344 XtVaSetValues(toplevel, XtNtitle, version, 0);
349 XSetWindowBackground (dpy, window,
350 get_pixel_resource ("background", "Background",
352 XClearWindow (dpy, window);
355 if (!root_p && !on_window)
356 /* wait for it to be mapped */
357 XIfEvent (dpy, &event, MapNotify_event_p, (XPointer) window);
360 srandom ((int) time ((time_t *) 0));
361 screenhack (dpy, window); /* doesn't return */