1 /* xscreensaver, Copyright (c) 1992, 1995, 1997
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/Xmu/Error.h>
44 # include <Xmu/Error.h>
49 #include "screenhack.h"
57 static XrmOptionDescRec default_options [] = {
58 { "-root", ".root", XrmoptionNoArg, "True" },
59 { "-window", ".root", XrmoptionNoArg, "False" },
60 { "-mono", ".mono", XrmoptionNoArg, "True" },
61 { "-install", ".installColormap", XrmoptionNoArg, "True" },
62 { "-noinstall",".installColormap", XrmoptionNoArg, "False" },
63 { "-visual", ".visualID", XrmoptionSepArg, 0 },
67 static char *default_defaults[] = {
69 "*geometry: 600x480", /* this should be .geometry, but nooooo... */
71 "*installColormap: false",
76 static XrmOptionDescRec *merged_options;
77 static int merged_options_size;
78 static char **merged_defaults;
83 int def_opts_size, opts_size;
84 int def_defaults_size, defaults_size;
86 for (def_opts_size = 0; default_options[def_opts_size].option;
89 for (opts_size = 0; options[opts_size].option; opts_size++)
92 merged_options_size = def_opts_size + opts_size;
93 merged_options = (XrmOptionDescRec *)
94 malloc ((merged_options_size + 1) * sizeof(*default_options));
95 memcpy (merged_options, default_options,
96 (def_opts_size * sizeof(*default_options)));
97 memcpy (merged_options + def_opts_size, options,
98 ((opts_size + 1) * sizeof(*default_options)));
100 for (def_defaults_size = 0; default_defaults[def_defaults_size];
103 for (defaults_size = 0; defaults[defaults_size]; defaults_size++)
105 merged_defaults = (char **)
106 malloc ((def_defaults_size + defaults_size + 1) * sizeof (*defaults));;
107 memcpy (merged_defaults, default_defaults,
108 def_defaults_size * sizeof(*defaults));
109 memcpy (merged_defaults + def_defaults_size, defaults,
110 (defaults_size + 1) * sizeof(*defaults));
114 /* Make the X errors print out the name of this program, so we have some
115 clue which one has a bug when they die under the screensaver.
119 screenhack_ehandler (Display *dpy, XErrorEvent *error)
121 fprintf (stderr, "\nX error in %s:\n", progname);
122 if (XmuPrintDefaultErrorMessage (dpy, error, stderr))
125 fprintf (stderr, " (nonfatal.)\n");
130 MapNotify_event_p (Display *dpy, XEvent *event, XPointer window)
132 return (event->xany.type == MapNotify &&
133 event->xvisibility.window == (Window) window);
138 extern Visual *get_gl_visual (Screen *, const char *, const char *);
142 extern void pre_merge_options (void);
148 main (int argc, char **argv)
158 Boolean dont_clear /*, dont_map */;
162 pre_merge_options ();
165 toplevel = XtAppInitialize (&app, progclass, merged_options,
166 merged_options_size, &argc, argv,
167 merged_defaults, 0, 0);
168 dpy = XtDisplay (toplevel);
169 db = XtDatabase (dpy);
170 XtGetApplicationNameAndClass (dpy, &progname, &progclass);
171 XSetErrorHandler (screenhack_ehandler);
174 char *v = (char *) strdup(strchr(screensaver_id, ' '));
175 char *s = (char *) strchr(v, ',');
177 sprintf (version, "%s: from the XScreenSaver%s distribution.",
188 Bool help_p = !strcmp(argv[1], "-help");
189 fprintf (stderr, "%s\n", version);
190 for (s = progclass; *s; s++) fprintf(stderr, " ");
191 fprintf (stderr, " http://people.netscape.com/jwz/xscreensaver/\n\n");
194 fprintf(stderr, "Unrecognised option: %s\n", argv[1]);
195 fprintf (stderr, "Options include: ");
196 for (i = 0; i < merged_options_size; i++)
198 char *sw = merged_options [i].option;
199 Bool argp = (merged_options [i].argKind == XrmoptionSepArg);
200 int size = strlen (sw) + (argp ? 6 : 0) + 2;
203 fprintf (stderr, "\n\t\t ");
207 fprintf (stderr, "%s", sw);
208 if (argp) fprintf (stderr, " <arg>");
209 if (i != merged_options_size - 1) fprintf (stderr, ", ");
211 fprintf (stderr, ".\n");
212 exit (help_p ? 0 : 1);
215 dont_clear = get_boolean_resource ("dontClearRoot", "Boolean");
216 /*dont_map = get_boolean_resource ("dontMapWindow", "Boolean"); */
217 mono_p = get_boolean_resource ("mono", "Boolean");
218 if (CellsOfScreen (DefaultScreenOfDisplay (dpy)) <= 2)
221 root_p = get_boolean_resource ("root", "Boolean");
224 XWindowAttributes xgwa;
225 window = RootWindowOfScreen (XtScreen (toplevel));
226 XtDestroyWidget (toplevel);
227 XGetWindowAttributes (dpy, window, &xgwa);
228 cmap = xgwa.colormap;
229 visual = xgwa.visual;
233 Boolean def_visual_p;
234 Screen *screen = XtScreen (toplevel);
237 visual = get_gl_visual (screen, "visualID", "VisualID");
239 visual = get_visual_resource (screen, "visualID", "VisualID", False);
242 if (toplevel->core.width <= 0)
243 toplevel->core.width = 600;
244 if (toplevel->core.height <= 0)
245 toplevel->core.height = 480;
247 def_visual_p = (visual == DefaultVisualOfScreen (screen));
254 cmap = XCreateColormap (dpy, RootWindowOfScreen(screen),
256 bg = get_pixel_resource ("background", "Background", dpy, cmap);
257 bd = get_pixel_resource ("borderColor", "Foreground", dpy, cmap);
259 new = XtVaAppCreateShell (progname, progclass,
260 topLevelShellWidgetClass, dpy,
261 XtNmappedWhenManaged, False,
263 XtNdepth, visual_depth (screen, visual),
264 XtNwidth, toplevel->core.width,
265 XtNheight, toplevel->core.height,
267 XtNbackground, (Pixel) bg,
268 XtNborderColor, (Pixel) bd,
270 XtDestroyWidget (toplevel);
272 XtRealizeWidget (toplevel);
273 window = XtWindow (toplevel);
277 XtVaSetValues (toplevel, XtNmappedWhenManaged, False, 0);
278 XtRealizeWidget (toplevel);
279 window = XtWindow (toplevel);
281 if (get_boolean_resource ("installColormap", "InstallColormap"))
283 cmap = XCreateColormap (dpy, window,
284 DefaultVisualOfScreen (XtScreen (toplevel)),
286 XSetWindowColormap (dpy, window, cmap);
290 cmap = DefaultColormap (dpy, DefaultScreen (dpy));
297 XtVaSetValues (toplevel, XtNmappedWhenManaged, False, 0);
298 XtRealizeWidget (toplevel);
303 XtPopup (toplevel, XtGrabNone);
306 XtVaSetValues(toplevel, XtNtitle, version, 0);
311 XSetWindowBackground (dpy, window,
312 get_pixel_resource ("background", "Background",
314 XClearWindow (dpy, window);
318 /* wait for it to be mapped */
319 XIfEvent (dpy, &event, MapNotify_event_p, (XPointer) window);
322 srandom ((int) time ((time_t *) 0));
323 screenhack (dpy, window); /* doesn't return */