1 /* xscreensaver, Copyright (c) 1992, 1995, 1997, 1998
2 * Jamie Zawinski <jwz@jwz.org>
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));
119 /* This totally sucks. Xt should behave like this by default.
120 If the string in `defaults' looks like ".foo", change that
125 for (s = merged_defaults; *s; s++)
128 const char *oldr = *s;
129 char *newr = (char *) malloc(strlen(oldr) + strlen(progclass) + 3);
130 strcpy (newr, progclass);
138 /* Make the X errors print out the name of this program, so we have some
139 clue which one has a bug when they die under the screensaver.
143 screenhack_ehandler (Display *dpy, XErrorEvent *error)
145 fprintf (stderr, "\nX error in %s:\n", progname);
146 if (XmuPrintDefaultErrorMessage (dpy, error, stderr))
149 fprintf (stderr, " (nonfatal.)\n");
154 MapNotify_event_p (Display *dpy, XEvent *event, XPointer window)
156 return (event->xany.type == MapNotify &&
157 event->xvisibility.window == (Window) window);
162 extern Visual *get_gl_visual (Screen *, const char *, const char *);
166 extern void pre_merge_options (void);
172 main (int argc, char **argv)
181 Window on_window = 0;
183 Boolean dont_clear /*, dont_map */;
187 pre_merge_options ();
192 /* We have to do this on SGI to prevent the background color from being
193 overridden by the current desktop color scheme (we'd like our backgrounds
194 to be black, thanks.) This should be the same as setting the
195 "*useSchemes: none" resource, but it's not -- if that resource is
196 present in the `default_defaults' above, it doesn't work, though it
197 does work when passed as an -xrm arg on the command line. So screw it,
198 turn them off from C instead.
200 SgiUseSchemes ("none");
203 toplevel = XtAppInitialize (&app, progclass, merged_options,
204 merged_options_size, &argc, argv,
205 merged_defaults, 0, 0);
206 dpy = XtDisplay (toplevel);
207 db = XtDatabase (dpy);
208 XtGetApplicationNameAndClass (dpy, &progname, &progclass);
209 XSetErrorHandler (screenhack_ehandler);
212 char *v = (char *) strdup(strchr(screensaver_id, ' '));
213 char *s = (char *) strchr(v, ',');
215 sprintf (version, "%s: from the XScreenSaver%s distribution.",
226 Bool help_p = !strcmp(argv[1], "-help");
227 fprintf (stderr, "%s\n", version);
228 for (s = progclass; *s; s++) fprintf(stderr, " ");
229 fprintf (stderr, " http://www.jwz.org/xscreensaver/\n\n");
232 fprintf(stderr, "Unrecognised option: %s\n", argv[1]);
233 fprintf (stderr, "Options include: ");
234 for (i = 0; i < merged_options_size; i++)
236 char *sw = merged_options [i].option;
237 Bool argp = (merged_options [i].argKind == XrmoptionSepArg);
238 int size = strlen (sw) + (argp ? 6 : 0) + 2;
241 fprintf (stderr, "\n\t\t ");
245 fprintf (stderr, "%s", sw);
246 if (argp) fprintf (stderr, " <arg>");
247 if (i != merged_options_size - 1) fprintf (stderr, ", ");
249 fprintf (stderr, ".\n");
250 exit (help_p ? 0 : 1);
253 dont_clear = get_boolean_resource ("dontClearRoot", "Boolean");
254 /*dont_map = get_boolean_resource ("dontMapWindow", "Boolean"); */
255 mono_p = get_boolean_resource ("mono", "Boolean");
256 if (CellsOfScreen (DefaultScreenOfDisplay (dpy)) <= 2)
259 root_p = get_boolean_resource ("root", "Boolean");
262 char *s = get_string_resource ("windowID", "WindowID");
264 on_window = get_integer_resource ("windowID", "WindowID");
270 XWindowAttributes xgwa;
271 window = (Window) on_window;
272 XtDestroyWidget (toplevel);
273 XGetWindowAttributes (dpy, window, &xgwa);
274 cmap = xgwa.colormap;
275 visual = xgwa.visual;
279 XWindowAttributes xgwa;
280 window = RootWindowOfScreen (XtScreen (toplevel));
281 XtDestroyWidget (toplevel);
282 XGetWindowAttributes (dpy, window, &xgwa);
283 cmap = xgwa.colormap;
284 visual = xgwa.visual;
288 Boolean def_visual_p;
289 Screen *screen = XtScreen (toplevel);
292 visual = get_gl_visual (screen, "visualID", "VisualID");
294 visual = get_visual_resource (screen, "visualID", "VisualID", False);
297 if (toplevel->core.width <= 0)
298 toplevel->core.width = 600;
299 if (toplevel->core.height <= 0)
300 toplevel->core.height = 480;
302 def_visual_p = (visual == DefaultVisualOfScreen (screen));
309 cmap = XCreateColormap (dpy, RootWindowOfScreen(screen),
311 bg = get_pixel_resource ("background", "Background", dpy, cmap);
312 bd = get_pixel_resource ("borderColor", "Foreground", dpy, cmap);
314 new = XtVaAppCreateShell (progname, progclass,
315 topLevelShellWidgetClass, dpy,
316 XtNmappedWhenManaged, False,
318 XtNdepth, visual_depth (screen, visual),
319 XtNwidth, toplevel->core.width,
320 XtNheight, toplevel->core.height,
322 XtNbackground, (Pixel) bg,
323 XtNborderColor, (Pixel) bd,
325 XtDestroyWidget (toplevel);
327 XtRealizeWidget (toplevel);
328 window = XtWindow (toplevel);
332 XtVaSetValues (toplevel, XtNmappedWhenManaged, False, 0);
333 XtRealizeWidget (toplevel);
334 window = XtWindow (toplevel);
336 if (get_boolean_resource ("installColormap", "InstallColormap"))
338 cmap = XCreateColormap (dpy, window,
339 DefaultVisualOfScreen (XtScreen (toplevel)),
341 XSetWindowColormap (dpy, window, cmap);
345 cmap = DefaultColormap (dpy, DefaultScreen (dpy));
352 XtVaSetValues (toplevel, XtNmappedWhenManaged, False, 0);
353 XtRealizeWidget (toplevel);
358 XtPopup (toplevel, XtGrabNone);
361 XtVaSetValues(toplevel, XtNtitle, version, 0);
366 XSetWindowBackground (dpy, window,
367 get_pixel_resource ("background", "Background",
369 XClearWindow (dpy, window);
372 if (!root_p && !on_window)
373 /* wait for it to be mapped */
374 XIfEvent (dpy, &event, MapNotify_event_p, (XPointer) window);
377 srandom ((int) time ((time_t *) 0));
378 screenhack (dpy, window); /* doesn't return */