http://www.ibiblio.org/pub/historic-linux/ftp-archives/sunsite.unc.edu/Sep-29-1996...
[xscreensaver] / hacks / screenhack.c
1 /* xscreensaver, Copyright (c) 1992, 1995 Jamie Zawinski <jwz@netscape.com>
2  *
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 
9  * implied warranty.
10  *
11  * And remember: X Windows is to graphics hacking as roman numerals are to
12  * the square root of pi.
13  */
14
15 /* This file contains simple code to open a window or draw on the root.
16    The idea being that, when writing a graphics hack, you can just link
17    with this .o to get all of the uninteresting junk out of the way.
18
19    -  create a procedure `screenhack(dpy, window)'
20
21    -  create a variable `char *progclass' which names this program's
22       resource class.
23
24    -  create a variable `char defaults []' for the default resources.
25
26    -  create a variable `XrmOptionDescRec options []' for the command-line,
27       and `int options_size' which is `XtNumber (options)'.
28
29    And that's it...
30  */
31
32 #include "version.h"
33
34 #include <stdio.h>
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>
40 #include <X11/Xmu/Error.h>
41 #include "screenhack.h"
42
43 char *progname;
44 XrmDatabase db;
45 Bool mono_p;
46
47 #if __STDC__
48 # define P(x) x
49 #else
50 # define P(x)()
51 #endif
52
53
54 static XrmOptionDescRec default_options [] = {
55   { "-root",    ".root",                XrmoptionNoArg, "True" },
56   { "-window",  ".root",                XrmoptionNoArg, "False" },
57   { "-mono",    ".mono",                XrmoptionNoArg, "True" },
58   { "-install", ".installColormap",     XrmoptionNoArg, "True" },
59   { "-visual",  ".visualID",            XrmoptionSepArg, 0 }
60 };
61
62 static char *default_defaults[] = {
63   "*root:               false",
64   "*geometry:           500x500", /* this should be .geometry, but nooooo... */
65   "*mono:               false",
66   "*installColormap:    false",
67   "*visualID:           default",
68   0
69 };
70
71 static XrmOptionDescRec *merged_options;
72 static int merged_options_size;
73 static char **merged_defaults;
74
75 static void
76 merge_options P((void))
77 {
78   int options_sizeof = options_size * sizeof (options[0]);
79   int defaults_size;
80   merged_options_size = XtNumber (default_options) + options_size;
81   merged_options = (XrmOptionDescRec *)
82     malloc (sizeof (default_options) + options_sizeof);
83   memcpy (merged_options, options, options_sizeof);
84   memcpy (merged_options + options_size, default_options,
85           sizeof (default_options));
86
87   for (defaults_size = 0; defaults [defaults_size]; defaults_size++);
88   merged_defaults = (char **)
89     malloc (sizeof (default_defaults) + (defaults_size * sizeof (char *)));
90   memcpy (merged_defaults, default_defaults, sizeof (default_defaults));
91   memcpy ((merged_defaults - 1 +
92            (sizeof (default_defaults) / sizeof (default_defaults[0]))),
93           defaults, ((defaults_size + 1) * sizeof (defaults[0])));
94 }
95
96 \f
97 /* Make the X errors print out the name of this program, so we have some
98    clue which one has a bug when they die under the screensaver.
99  */
100
101 static int
102 screenhack_ehandler (dpy, error)
103      Display *dpy;
104      XErrorEvent *error;
105 {
106   fprintf (stderr, "\nX error in %s:\n", progname);
107   if (XmuPrintDefaultErrorMessage (dpy, error, stderr))
108     exit (-1);
109   else
110     fprintf (stderr, " (nonfatal.)\n");
111   return 0;
112 }
113
114 static Bool
115 MapNotify_event_p (dpy, event, window)
116      Display *dpy;
117      XEvent *event;
118      XPointer window;
119 {
120   return (event->xany.type == MapNotify &&
121           event->xvisibility.window == (Window) window);
122 }
123
124
125 void
126 main (argc, argv)
127      int argc;
128      char **argv;
129 {
130   XtAppContext app;
131   Widget toplevel;
132   Display *dpy;
133   Window window;
134   Visual *visual;
135   Colormap cmap;
136   Bool root_p;
137   XEvent event;
138
139   merge_options ();
140   toplevel = XtAppInitialize (&app, progclass, merged_options,
141                               merged_options_size, &argc, argv,
142                               merged_defaults, 0, 0);
143   dpy = XtDisplay (toplevel);
144   db = XtDatabase (dpy);
145   XtGetApplicationNameAndClass (dpy, &progname, &progclass);
146   XSetErrorHandler (screenhack_ehandler);
147   if (argc > 1)
148     {
149       int i;
150       int x = 18;
151       int end = 78;
152       fprintf (stderr, "%s: unrecognised option \"%s\"\n", progname, argv[1]);
153       fprintf (stderr, "Options include: ");
154       for (i = 0; i < merged_options_size; i++)
155         {
156           char *sw = merged_options [i].option;
157           Bool argp = (merged_options [i].argKind == XrmoptionSepArg);
158           int size = strlen (sw) + (argp ? 6 : 0) + 2;
159           if (x + size >= end)
160             {
161               fprintf (stderr, "\n\t\t ");
162               x = 18;
163             }
164           x += size;
165           fprintf (stderr, "%s", sw);
166           if (argp) fprintf (stderr, " <arg>");
167           if (i != merged_options_size - 1) fprintf (stderr, ", ");
168         }
169       fprintf (stderr, ".\n");
170       exit (1);
171     }
172
173   mono_p = get_boolean_resource ("mono", "Boolean");
174   if (CellsOfScreen (DefaultScreenOfDisplay (dpy)) <= 2)
175     mono_p = True;
176
177   root_p = get_boolean_resource ("root", "Boolean");
178   if (root_p)
179     {
180       XWindowAttributes xgwa;
181       window = RootWindowOfScreen (XtScreen (toplevel));
182       XtDestroyWidget (toplevel);
183       XGetWindowAttributes (dpy, window, &xgwa);
184       cmap = xgwa.colormap;
185       visual = xgwa.visual;
186     }
187   else
188     {
189       visual = get_visual_resource (dpy, "visualID", "VisualID");
190
191       XtVaSetValues (toplevel, XtNmappedWhenManaged, False, 0);
192       XtRealizeWidget (toplevel);
193       window = XtWindow (toplevel);
194
195       if (visual != DefaultVisualOfScreen (XtScreen (toplevel)))
196         {
197           Arg av [20];
198           int ac;
199           unsigned int bg, bd;
200           Widget new;
201           cmap = XCreateColormap (dpy, window, visual, AllocNone);
202           bg = get_pixel_resource ("background", "Background", dpy, cmap);
203           bd = get_pixel_resource ("borderColor", "Foreground", dpy, cmap);
204           ac = 0;
205           XtSetArg (av[ac], XtNvisual, visual); ac++;
206           XtSetArg (av[ac], XtNcolormap, cmap); ac++;
207           XtSetArg (av[ac], XtNdepth, get_visual_depth (dpy, visual)); ac++;
208           XtSetArg (av[ac], XtNbackground, (Pixel) bg); ac++;
209           XtSetArg (av[ac], XtNborderColor, (Pixel) bd); ac++;
210           new = XtAppCreateShell (progname, progclass,
211                                   topLevelShellWidgetClass, dpy,
212                                   av, ac);
213           XtDestroyWidget (toplevel);
214           toplevel = new;
215         }
216       else if (get_boolean_resource ("installColormap", "InstallColormap"))
217         {
218           cmap = XCreateColormap (dpy, window,
219                                   DefaultVisualOfScreen (XtScreen (toplevel)),
220                                   AllocNone);
221           XSetWindowColormap (dpy, window, cmap);
222         }
223       else
224         {
225           cmap = DefaultColormap (dpy, DefaultScreen (dpy));
226         }
227
228       XtPopup (toplevel, XtGrabNone);
229       window = XtWindow (toplevel);
230     }
231
232   if (!get_boolean_resource ("dontClearWindow", "Boolean")) /* kludge-o-rama */
233     {
234       XSetWindowBackground (dpy, window,
235                             get_pixel_resource ("background", "Background",
236                                                 dpy, cmap));
237       XClearWindow (dpy, window);
238     }
239
240   if (!root_p && toplevel->core.mapped_when_managed)
241     /* wait for it to be mapped */
242     XIfEvent (dpy, &event, MapNotify_event_p, (XPointer) window);
243
244   XSync (dpy, False);
245   srandom ((int) time ((time_t *) 0));
246   screenhack (dpy, window);
247 }