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/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 },
64 { "-window-id", ".windowID", XrmoptionSepArg, 0 },
68 static char *default_defaults[] = {
70 "*geometry: 600x480", /* this should be .geometry, but nooooo... */
72 "*installColormap: false",
78 static XrmOptionDescRec *merged_options;
79 static int merged_options_size;
80 static char **merged_defaults;
85 int def_opts_size, opts_size;
86 int def_defaults_size, defaults_size;
88 for (def_opts_size = 0; default_options[def_opts_size].option;
91 for (opts_size = 0; options[opts_size].option; opts_size++)
94 merged_options_size = def_opts_size + opts_size;
95 merged_options = (XrmOptionDescRec *)
96 malloc ((merged_options_size + 1) * sizeof(*default_options));
97 memcpy (merged_options, default_options,
98 (def_opts_size * sizeof(*default_options)));
99 memcpy (merged_options + def_opts_size, options,
100 ((opts_size + 1) * sizeof(*default_options)));
102 for (def_defaults_size = 0; default_defaults[def_defaults_size];
105 for (defaults_size = 0; defaults[defaults_size]; defaults_size++)
107 merged_defaults = (char **)
108 malloc ((def_defaults_size + defaults_size + 1) * sizeof (*defaults));;
109 memcpy (merged_defaults, default_defaults,
110 def_defaults_size * sizeof(*defaults));
111 memcpy (merged_defaults + def_defaults_size, defaults,
112 (defaults_size + 1) * sizeof(*defaults));
116 /* Make the X errors print out the name of this program, so we have some
117 clue which one has a bug when they die under the screensaver.
121 screenhack_ehandler (Display *dpy, XErrorEvent *error)
123 fprintf (stderr, "\nX error in %s:\n", progname);
124 if (XmuPrintDefaultErrorMessage (dpy, error, stderr))
127 fprintf (stderr, " (nonfatal.)\n");
132 MapNotify_event_p (Display *dpy, XEvent *event, XPointer window)
134 return (event->xany.type == MapNotify &&
135 event->xvisibility.window == (Window) window);
140 extern Visual *get_gl_visual (Screen *, const char *, const char *);
144 extern void pre_merge_options (void);
150 main (int argc, char **argv)
159 Window on_window = 0;
161 Boolean dont_clear /*, dont_map */;
165 pre_merge_options ();
168 toplevel = XtAppInitialize (&app, progclass, merged_options,
169 merged_options_size, &argc, argv,
170 merged_defaults, 0, 0);
171 dpy = XtDisplay (toplevel);
172 db = XtDatabase (dpy);
173 XtGetApplicationNameAndClass (dpy, &progname, &progclass);
174 XSetErrorHandler (screenhack_ehandler);
177 char *v = (char *) strdup(strchr(screensaver_id, ' '));
178 char *s = (char *) strchr(v, ',');
180 sprintf (version, "%s: from the XScreenSaver%s distribution.",
191 Bool help_p = !strcmp(argv[1], "-help");
192 fprintf (stderr, "%s\n", version);
193 for (s = progclass; *s; s++) fprintf(stderr, " ");
194 fprintf (stderr, " http://people.netscape.com/jwz/xscreensaver/\n\n");
197 fprintf(stderr, "Unrecognised option: %s\n", argv[1]);
198 fprintf (stderr, "Options include: ");
199 for (i = 0; i < merged_options_size; i++)
201 char *sw = merged_options [i].option;
202 Bool argp = (merged_options [i].argKind == XrmoptionSepArg);
203 int size = strlen (sw) + (argp ? 6 : 0) + 2;
206 fprintf (stderr, "\n\t\t ");
210 fprintf (stderr, "%s", sw);
211 if (argp) fprintf (stderr, " <arg>");
212 if (i != merged_options_size - 1) fprintf (stderr, ", ");
214 fprintf (stderr, ".\n");
215 exit (help_p ? 0 : 1);
218 dont_clear = get_boolean_resource ("dontClearRoot", "Boolean");
219 /*dont_map = get_boolean_resource ("dontMapWindow", "Boolean"); */
220 mono_p = get_boolean_resource ("mono", "Boolean");
221 if (CellsOfScreen (DefaultScreenOfDisplay (dpy)) <= 2)
224 root_p = get_boolean_resource ("root", "Boolean");
227 char *s = get_string_resource ("windowID", "WindowID");
229 on_window = get_integer_resource ("windowID", "WindowID");
235 XWindowAttributes xgwa;
236 window = (Window) on_window;
237 XtDestroyWidget (toplevel);
238 XGetWindowAttributes (dpy, window, &xgwa);
239 cmap = xgwa.colormap;
240 visual = xgwa.visual;
244 XWindowAttributes xgwa;
245 window = RootWindowOfScreen (XtScreen (toplevel));
246 XtDestroyWidget (toplevel);
247 XGetWindowAttributes (dpy, window, &xgwa);
248 cmap = xgwa.colormap;
249 visual = xgwa.visual;
253 Boolean def_visual_p;
254 Screen *screen = XtScreen (toplevel);
257 visual = get_gl_visual (screen, "visualID", "VisualID");
259 visual = get_visual_resource (screen, "visualID", "VisualID", False);
262 if (toplevel->core.width <= 0)
263 toplevel->core.width = 600;
264 if (toplevel->core.height <= 0)
265 toplevel->core.height = 480;
267 def_visual_p = (visual == DefaultVisualOfScreen (screen));
274 cmap = XCreateColormap (dpy, RootWindowOfScreen(screen),
276 bg = get_pixel_resource ("background", "Background", dpy, cmap);
277 bd = get_pixel_resource ("borderColor", "Foreground", dpy, cmap);
279 new = XtVaAppCreateShell (progname, progclass,
280 topLevelShellWidgetClass, dpy,
281 XtNmappedWhenManaged, False,
283 XtNdepth, visual_depth (screen, visual),
284 XtNwidth, toplevel->core.width,
285 XtNheight, toplevel->core.height,
287 XtNbackground, (Pixel) bg,
288 XtNborderColor, (Pixel) bd,
290 XtDestroyWidget (toplevel);
292 XtRealizeWidget (toplevel);
293 window = XtWindow (toplevel);
297 XtVaSetValues (toplevel, XtNmappedWhenManaged, False, 0);
298 XtRealizeWidget (toplevel);
299 window = XtWindow (toplevel);
301 if (get_boolean_resource ("installColormap", "InstallColormap"))
303 cmap = XCreateColormap (dpy, window,
304 DefaultVisualOfScreen (XtScreen (toplevel)),
306 XSetWindowColormap (dpy, window, cmap);
310 cmap = DefaultColormap (dpy, DefaultScreen (dpy));
317 XtVaSetValues (toplevel, XtNmappedWhenManaged, False, 0);
318 XtRealizeWidget (toplevel);
323 XtPopup (toplevel, XtGrabNone);
326 XtVaSetValues(toplevel, XtNtitle, version, 0);
331 XSetWindowBackground (dpy, window,
332 get_pixel_resource ("background", "Background",
334 XClearWindow (dpy, window);
337 if (!root_p && !on_window)
338 /* wait for it to be mapped */
339 XIfEvent (dpy, &event, MapNotify_event_p, (XPointer) window);
342 srandom ((int) time ((time_t *) 0));
343 screenhack (dpy, window); /* doesn't return */